1/* 2 * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 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 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. 16 * 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. 27 */ 28 29#if !PLATFORM(IOS) 30 31#import "WebNSPasteboardExtras.h" 32 33#import "DOMElementInternal.h" 34#import "WebArchive.h" 35#import "WebFrameInternal.h" 36#import "WebHTMLViewInternal.h" 37#import "WebNSURLExtras.h" 38#import "WebResourcePrivate.h" 39#import "WebURLsWithTitles.h" 40#import "WebViewPrivate.h" 41#import <WebCore/CachedImage.h> 42#import <WebCore/Element.h> 43#import <WebCore/Image.h> 44#import <WebCore/MIMETypeRegistry.h> 45#import <WebCore/RenderImage.h> 46#import <WebKitLegacy/DOMExtensions.h> 47#import <WebKitLegacy/DOMPrivate.h> 48#import <WebKitSystemInterface.h> 49#import <wtf/Assertions.h> 50#import <wtf/RetainPtr.h> 51#import <wtf/StdLibExtras.h> 52 53using namespace WebCore; 54 55NSString *WebURLPboardType = @"public.url"; 56NSString *WebURLNamePboardType = @"public.url-name"; 57 58@implementation NSPasteboard (WebExtras) 59 60+ (NSArray *)_web_writableTypesForURL 61{ 62 DEPRECATED_DEFINE_STATIC_LOCAL(RetainPtr<NSArray>, types, ([[NSArray alloc] initWithObjects: 63 WebURLsWithTitlesPboardType, 64 NSURLPboardType, 65 WebURLPboardType, 66 WebURLNamePboardType, 67 NSStringPboardType, 68 nil])); 69 return types.get(); 70} 71 72static inline NSArray *_createWritableTypesForImageWithoutArchive() 73{ 74 NSMutableArray *types = [[NSMutableArray alloc] initWithObjects:NSTIFFPboardType, nil]; 75 [types addObjectsFromArray:[NSPasteboard _web_writableTypesForURL]]; 76 return types; 77} 78 79static NSArray *_writableTypesForImageWithoutArchive (void) 80{ 81 DEPRECATED_DEFINE_STATIC_LOCAL(RetainPtr<NSArray>, types, (_createWritableTypesForImageWithoutArchive())); 82 return types.get(); 83} 84 85static inline NSArray *_createWritableTypesForImageWithArchive() 86{ 87 NSMutableArray *types = [_writableTypesForImageWithoutArchive() mutableCopy]; 88 [types addObject:NSRTFDPboardType]; 89 [types addObject:WebArchivePboardType]; 90 return types; 91} 92 93static NSArray *_writableTypesForImageWithArchive (void) 94{ 95 DEPRECATED_DEFINE_STATIC_LOCAL(RetainPtr<NSArray>, types, (_createWritableTypesForImageWithArchive())); 96 return types.get(); 97} 98 99+ (NSArray *)_web_writableTypesForImageIncludingArchive:(BOOL)hasArchive 100{ 101 return hasArchive 102 ? _writableTypesForImageWithArchive() 103 : _writableTypesForImageWithoutArchive(); 104} 105 106+ (NSArray *)_web_dragTypesForURL 107{ 108 return [NSArray arrayWithObjects: 109 WebURLsWithTitlesPboardType, 110 NSURLPboardType, 111 WebURLPboardType, 112 WebURLNamePboardType, 113 NSStringPboardType, 114 NSFilenamesPboardType, 115 nil]; 116} 117 118- (NSURL *)_web_bestURL 119{ 120 NSArray *types = [self types]; 121 122 if ([types containsObject:NSURLPboardType]) { 123 NSURL *URLFromPasteboard = [NSURL URLFromPasteboard:self]; 124 NSString *scheme = [URLFromPasteboard scheme]; 125 if ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"]) { 126 return [URLFromPasteboard _webkit_canonicalize]; 127 } 128 } 129 130 if ([types containsObject:NSStringPboardType]) { 131 NSString *URLString = [self stringForType:NSStringPboardType]; 132 if ([URLString _webkit_looksLikeAbsoluteURL]) { 133 NSURL *URL = [[NSURL _web_URLWithUserTypedString:URLString] _webkit_canonicalize]; 134 if (URL) { 135 return URL; 136 } 137 } 138 } 139 140 if ([types containsObject:NSFilenamesPboardType]) { 141 NSArray *files = [self propertyListForType:NSFilenamesPboardType]; 142 // FIXME: Maybe it makes more sense to allow multiple files and only use the first one? 143 if ([files count] == 1) { 144 NSString *file = [files objectAtIndex:0]; 145 // FIXME: We are filtering out directories because that's what the original code used to 146 // do. Without this check, if the URL points to a local directory, Safari will open the 147 // parent directory of the directory in Finder. This check should go away as soon as 148 // possible. 149 BOOL isDirectory; 150 if ([[NSFileManager defaultManager] fileExistsAtPath:file isDirectory:&isDirectory] && isDirectory) 151 return nil; 152 return [[NSURL fileURLWithPath:file] _webkit_canonicalize]; 153 } 154 } 155 156 return nil; 157} 158 159- (void)_web_writeURL:(NSURL *)URL andTitle:(NSString *)title types:(NSArray *)types 160{ 161 ASSERT(URL); 162 163 if ([title length] == 0) { 164 title = [[URL path] lastPathComponent]; 165 if ([title length] == 0) 166 title = [URL _web_userVisibleString]; 167 } 168 169 if ([types containsObject:NSURLPboardType]) 170 [URL writeToPasteboard:self]; 171 if ([types containsObject:WebURLPboardType]) 172 [self setString:[URL _web_originalDataAsString] forType:WebURLPboardType]; 173 if ([types containsObject:WebURLNamePboardType]) 174 [self setString:title forType:WebURLNamePboardType]; 175 if ([types containsObject:NSStringPboardType]) 176 [self setString:[URL _web_userVisibleString] forType:NSStringPboardType]; 177 if ([types containsObject:WebURLsWithTitlesPboardType]) 178 [WebURLsWithTitles writeURLs:[NSArray arrayWithObject:URL] andTitles:[NSArray arrayWithObject:title] toPasteboard:self]; 179} 180 181+ (int)_web_setFindPasteboardString:(NSString *)string withOwner:(id)owner 182{ 183 NSPasteboard *findPasteboard = [NSPasteboard pasteboardWithName:NSFindPboard]; 184 [findPasteboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:owner]; 185 [findPasteboard setString:string forType:NSStringPboardType]; 186 return [findPasteboard changeCount]; 187} 188 189- (void)_web_writeFileWrapperAsRTFDAttachment:(NSFileWrapper *)wrapper 190{ 191 NSTextAttachment *attachment = [[NSTextAttachment alloc] initWithFileWrapper:wrapper]; 192 193 NSAttributedString *string = [NSAttributedString attributedStringWithAttachment:attachment]; 194 [attachment release]; 195 196 NSData *RTFDData = [string RTFDFromRange:NSMakeRange(0, [string length]) documentAttributes:nil]; 197 [self setData:RTFDData forType:NSRTFDPboardType]; 198} 199 200 201- (void)_web_writePromisedRTFDFromArchive:(WebArchive*)archive containsImage:(BOOL)containsImage 202{ 203 ASSERT(archive); 204 // This image data is either the only subresource of an archive (HTML image case) 205 // or the main resource (standalone image case). 206 NSArray *subresources = [archive subresources]; 207 WebResource *resource = [archive mainResource]; 208 if (containsImage && [subresources count] > 0 209 && MIMETypeRegistry::isSupportedImageResourceMIMEType([[subresources objectAtIndex:0] MIMEType])) 210 resource = (WebResource *)[subresources objectAtIndex:0]; 211 ASSERT(resource != nil); 212 213 ASSERT(!containsImage || MIMETypeRegistry::isSupportedImageResourceMIMEType([resource MIMEType])); 214 if (!containsImage || MIMETypeRegistry::isSupportedImageResourceMIMEType([resource MIMEType])) 215 [self _web_writeFileWrapperAsRTFDAttachment:[resource _fileWrapperRepresentation]]; 216 217} 218 219static CachedImage* imageFromElement(DOMElement *domElement) 220{ 221 Element* element = core(domElement); 222 if (!element) 223 return 0; 224 225 RenderObject* renderer = element->renderer(); 226 RenderImage* imageRenderer = toRenderImage(renderer); 227 if (!imageRenderer->cachedImage() || imageRenderer->cachedImage()->errorOccurred()) 228 return 0; 229 return imageRenderer->cachedImage(); 230} 231 232- (void)_web_writeImage:(NSImage *)image 233 element:(DOMElement *)element 234 URL:(NSURL *)URL 235 title:(NSString *)title 236 archive:(WebArchive *)archive 237 types:(NSArray *)types 238 source:(WebHTMLView *)source 239{ 240 ASSERT(image || element); 241 ASSERT(URL); 242 243 [self _web_writeURL:URL andTitle:title types:types]; 244 245 if ([types containsObject:NSTIFFPboardType]) { 246 if (image) 247 [self setData:[image TIFFRepresentation] forType:NSTIFFPboardType]; 248 else if (source && element) 249 [source setPromisedDragTIFFDataSource:imageFromElement(element)]; 250 else if (element) 251 [self setData:[element _imageTIFFRepresentation] forType:NSTIFFPboardType]; 252 } 253 254 if (archive) { 255 if ([types containsObject:WebArchivePboardType]) 256 [self setData:[archive data] forType:WebArchivePboardType]; 257 return; 258 } 259 260 // We should not have declared types that we aren't going to write (4031826). 261 ASSERT(![types containsObject:NSRTFDPboardType]); 262 ASSERT(![types containsObject:WebArchivePboardType]); 263} 264 265- (id)_web_declareAndWriteDragImageForElement:(DOMElement *)element 266 URL:(NSURL *)URL 267 title:(NSString *)title 268 archive:(WebArchive *)archive 269 source:(WebHTMLView *)source 270{ 271 ASSERT(self == [NSPasteboard pasteboardWithName:NSDragPboard]); 272 273 NSString *extension = @""; 274 if (RenderObject* renderer = core(element)->renderer()) { 275 if (renderer->isRenderImage()) { 276 if (CachedImage* image = toRenderImage(renderer)->cachedImage()) { 277 extension = image->image()->filenameExtension(); 278 if (![extension length]) 279 return 0; 280 } 281 } 282 } 283 284 NSMutableArray *types = [[NSMutableArray alloc] initWithObjects:NSFilesPromisePboardType, nil]; 285 [types addObjectsFromArray:[NSPasteboard _web_writableTypesForImageIncludingArchive:(archive != nil)]]; 286 [self declareTypes:types owner:source]; 287 [self _web_writeImage:nil element:element URL:URL title:title archive:archive types:types source:source]; 288 [types release]; 289 290 NSArray *extensions = [[NSArray alloc] initWithObjects:extension, nil]; 291 [self setPropertyList:extensions forType:NSFilesPromisePboardType]; 292 [extensions release]; 293 294 return source; 295} 296 297@end 298 299#endif // !PLATFORM(IOS) 300