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 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. 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#import "WebNSPasteboardExtras.h" 30 31#import "WebArchive.h" 32#import "WebFrameInternal.h" 33#import "WebHTMLViewInternal.h" 34#import "WebNSURLExtras.h" 35#import "WebResourcePrivate.h" 36#import "WebURLsWithTitles.h" 37#import "WebViewPrivate.h" 38#import <WebCore/Element.h> 39#import <WebCore/MIMETypeRegistry.h> 40#import <WebCore/RenderImage.h> 41#import <WebKit/DOMExtensions.h> 42#import <WebKit/DOMPrivate.h> 43#import <wtf/Assertions.h> 44#import <wtf/StdLibExtras.h> 45#import <wtf/RetainPtr.h> 46#import <WebKitSystemInterface.h> 47 48@interface NSFilePromiseDragSource : NSObject 49- initWithSource:(id)draggingSource; 50- (void)setTypes:(NSArray *)types onPasteboard:(NSPasteboard *)pboard; 51@end 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 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 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 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 if ([files count] == 1) { 143 NSString *file = [files objectAtIndex:0]; 144 BOOL isDirectory; 145 if([[NSFileManager defaultManager] fileExistsAtPath:file isDirectory:&isDirectory] && !isDirectory){ 146 return [[NSURL fileURLWithPath:file] _webkit_canonicalize]; 147 } 148 } 149 } 150 151 return nil; 152} 153 154- (void)_web_writeURL:(NSURL *)URL andTitle:(NSString *)title types:(NSArray *)types 155{ 156 ASSERT(URL); 157 158 if ([title length] == 0) { 159 title = [[URL path] lastPathComponent]; 160 if ([title length] == 0) 161 title = [URL _web_userVisibleString]; 162 } 163 164 if ([types containsObject:NSURLPboardType]) 165 [URL writeToPasteboard:self]; 166 if ([types containsObject:WebURLPboardType]) 167 [self setString:[URL _web_originalDataAsString] forType:WebURLPboardType]; 168 if ([types containsObject:WebURLNamePboardType]) 169 [self setString:title forType:WebURLNamePboardType]; 170 if ([types containsObject:NSStringPboardType]) 171 [self setString:[URL _web_userVisibleString] forType:NSStringPboardType]; 172 if ([types containsObject:WebURLsWithTitlesPboardType]) 173 [WebURLsWithTitles writeURLs:[NSArray arrayWithObject:URL] andTitles:[NSArray arrayWithObject:title] toPasteboard:self]; 174} 175 176+ (int)_web_setFindPasteboardString:(NSString *)string withOwner:(id)owner 177{ 178 NSPasteboard *findPasteboard = [NSPasteboard pasteboardWithName:NSFindPboard]; 179 [findPasteboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:owner]; 180 [findPasteboard setString:string forType:NSStringPboardType]; 181 return [findPasteboard changeCount]; 182} 183 184- (void)_web_writeFileWrapperAsRTFDAttachment:(NSFileWrapper *)wrapper 185{ 186 NSTextAttachment *attachment = [[NSTextAttachment alloc] initWithFileWrapper:wrapper]; 187 188 NSAttributedString *string = [NSAttributedString attributedStringWithAttachment:attachment]; 189 [attachment release]; 190 191 NSData *RTFDData = [string RTFDFromRange:NSMakeRange(0, [string length]) documentAttributes:nil]; 192 [self setData:RTFDData forType:NSRTFDPboardType]; 193} 194 195 196- (void)_web_writePromisedRTFDFromArchive:(WebArchive*)archive containsImage:(BOOL)containsImage 197{ 198 ASSERT(archive); 199 // This image data is either the only subresource of an archive (HTML image case) 200 // or the main resource (standalone image case). 201 NSArray *subresources = [archive subresources]; 202 WebResource *resource = [archive mainResource]; 203 if (containsImage && [subresources count] > 0 204 && MIMETypeRegistry::isSupportedImageResourceMIMEType([[subresources objectAtIndex:0] MIMEType])) 205 resource = (WebResource *)[subresources objectAtIndex:0]; 206 ASSERT(resource != nil); 207 208 ASSERT(!containsImage || MIMETypeRegistry::isSupportedImageResourceMIMEType([resource MIMEType])); 209 if (!containsImage || MIMETypeRegistry::isSupportedImageResourceMIMEType([resource MIMEType])) 210 [self _web_writeFileWrapperAsRTFDAttachment:[resource _fileWrapperRepresentation]]; 211 212} 213 214static CachedImage* imageFromElement(DOMElement *domElement) { 215 Element* element = core(domElement); 216 if (!element) 217 return 0; 218 219 RenderObject* renderer = element->renderer(); 220 RenderImage* imageRenderer = static_cast<RenderImage*>(renderer); 221 if (!imageRenderer->cachedImage() || imageRenderer->cachedImage()->errorOccurred()) 222 return 0; 223 return imageRenderer->cachedImage(); 224} 225 226- (void)_web_writeImage:(NSImage *)image 227 element:(DOMElement *)element 228 URL:(NSURL *)URL 229 title:(NSString *)title 230 archive:(WebArchive *)archive 231 types:(NSArray *)types 232 source:(WebHTMLView *)source 233{ 234 ASSERT(image || element); 235 ASSERT(URL); 236 237 [self _web_writeURL:URL andTitle:title types:types]; 238 239 if ([types containsObject:NSTIFFPboardType]) { 240 if (image) 241 [self setData:[image TIFFRepresentation] forType:NSTIFFPboardType]; 242 else if (source && element) 243 [source setPromisedDragTIFFDataSource:imageFromElement(element)]; 244 else if (element) 245 [self setData:[element _imageTIFFRepresentation] forType:NSTIFFPboardType]; 246 } 247 248 if (archive) 249 if ([types containsObject:WebArchivePboardType]) 250 [self setData:[archive data] forType:WebArchivePboardType]; 251 else { 252 // We should not have declared types that we aren't going to write (4031826). 253 ASSERT(![types containsObject:NSRTFDPboardType]); 254 ASSERT(![types containsObject:WebArchivePboardType]); 255 } 256} 257 258- (id)_web_declareAndWriteDragImageForElement:(DOMElement *)element 259 URL:(NSURL *)URL 260 title:(NSString *)title 261 archive:(WebArchive *)archive 262 source:(WebHTMLView *)source 263{ 264 ASSERT(self == [NSPasteboard pasteboardWithName:NSDragPboard]); 265 266 NSString *extension = @""; 267 if (RenderObject* renderer = core(element)->renderer()) { 268 if (renderer->isImage()) { 269 if (CachedImage* image = static_cast<RenderImage*>(renderer)->cachedImage()) { 270 extension = image->image()->filenameExtension(); 271 if (![extension length]) 272 return 0; 273 } 274 } 275 } 276 277 NSMutableArray *types = [[NSMutableArray alloc] initWithObjects:NSFilesPromisePboardType, nil]; 278 [types addObjectsFromArray:[NSPasteboard _web_writableTypesForImageIncludingArchive:(archive != nil)]]; 279 [self declareTypes:types owner:source]; 280 [self _web_writeImage:nil element:element URL:URL title:title archive:archive types:types source:source]; 281 [types release]; 282 283 NSArray *extensions = [[NSArray alloc] initWithObjects:extension, nil]; 284 [self setPropertyList:extensions forType:NSFilesPromisePboardType]; 285 [extensions release]; 286 287 return source; 288} 289 290@end 291