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