| /* |
| * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of |
| * its contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
| * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #import "WebNSPasteboardExtras.h" |
| |
| #import "DOMElementInternal.h" |
| #import "WebArchive.h" |
| #import "WebFrameInternal.h" |
| #import "WebHTMLViewInternal.h" |
| #import "WebNSURLExtras.h" |
| #import "WebResourcePrivate.h" |
| #import "WebURLsWithTitles.h" |
| #import "WebViewPrivate.h" |
| #import <WebCore/Element.h> |
| #import <WebCore/Image.h> |
| #import <WebCore/MIMETypeRegistry.h> |
| #import <WebCore/RenderImage.h> |
| #import <WebKit/DOMExtensions.h> |
| #import <WebKit/DOMPrivate.h> |
| #import <WebKitSystemInterface.h> |
| #import <wtf/Assertions.h> |
| #import <wtf/RetainPtr.h> |
| #import <wtf/StdLibExtras.h> |
| |
| using namespace WebCore; |
| |
| NSString *WebURLPboardType = @"public.url"; |
| NSString *WebURLNamePboardType = @"public.url-name"; |
| |
| @implementation NSPasteboard (WebExtras) |
| |
| + (NSArray *)_web_writableTypesForURL |
| { |
| DEFINE_STATIC_LOCAL(RetainPtr<NSArray>, types, ([[NSArray alloc] initWithObjects: |
| WebURLsWithTitlesPboardType, |
| NSURLPboardType, |
| WebURLPboardType, |
| WebURLNamePboardType, |
| NSStringPboardType, |
| nil])); |
| return types.get(); |
| } |
| |
| static inline NSArray *_createWritableTypesForImageWithoutArchive() |
| { |
| NSMutableArray *types = [[NSMutableArray alloc] initWithObjects:NSTIFFPboardType, nil]; |
| [types addObjectsFromArray:[NSPasteboard _web_writableTypesForURL]]; |
| return types; |
| } |
| |
| static NSArray *_writableTypesForImageWithoutArchive (void) |
| { |
| DEFINE_STATIC_LOCAL(RetainPtr<NSArray>, types, (_createWritableTypesForImageWithoutArchive())); |
| return types.get(); |
| } |
| |
| static inline NSArray *_createWritableTypesForImageWithArchive() |
| { |
| NSMutableArray *types = [_writableTypesForImageWithoutArchive() mutableCopy]; |
| [types addObject:NSRTFDPboardType]; |
| [types addObject:WebArchivePboardType]; |
| return types; |
| } |
| |
| static NSArray *_writableTypesForImageWithArchive (void) |
| { |
| DEFINE_STATIC_LOCAL(RetainPtr<NSArray>, types, (_createWritableTypesForImageWithArchive())); |
| return types.get(); |
| } |
| |
| + (NSArray *)_web_writableTypesForImageIncludingArchive:(BOOL)hasArchive |
| { |
| return hasArchive |
| ? _writableTypesForImageWithArchive() |
| : _writableTypesForImageWithoutArchive(); |
| } |
| |
| + (NSArray *)_web_dragTypesForURL |
| { |
| return [NSArray arrayWithObjects: |
| WebURLsWithTitlesPboardType, |
| NSURLPboardType, |
| WebURLPboardType, |
| WebURLNamePboardType, |
| NSStringPboardType, |
| NSFilenamesPboardType, |
| nil]; |
| } |
| |
| - (NSURL *)_web_bestURL |
| { |
| NSArray *types = [self types]; |
| |
| if ([types containsObject:NSURLPboardType]) { |
| NSURL *URLFromPasteboard = [NSURL URLFromPasteboard:self]; |
| NSString *scheme = [URLFromPasteboard scheme]; |
| if ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"]) { |
| return [URLFromPasteboard _webkit_canonicalize]; |
| } |
| } |
| |
| if ([types containsObject:NSStringPboardType]) { |
| NSString *URLString = [self stringForType:NSStringPboardType]; |
| if ([URLString _webkit_looksLikeAbsoluteURL]) { |
| NSURL *URL = [[NSURL _web_URLWithUserTypedString:URLString] _webkit_canonicalize]; |
| if (URL) { |
| return URL; |
| } |
| } |
| } |
| |
| if ([types containsObject:NSFilenamesPboardType]) { |
| NSArray *files = [self propertyListForType:NSFilenamesPboardType]; |
| // FIXME: Maybe it makes more sense to allow multiple files and only use the first one? |
| if ([files count] == 1) { |
| NSString *file = [files objectAtIndex:0]; |
| // FIXME: We are filtering out directories because that's what the original code used to |
| // do. Without this check, if the URL points to a local directory, Safari will open the |
| // parent directory of the directory in Finder. This check should go away as soon as |
| // possible. |
| BOOL isDirectory; |
| if ([[NSFileManager defaultManager] fileExistsAtPath:file isDirectory:&isDirectory] && isDirectory) |
| return nil; |
| return [[NSURL fileURLWithPath:file] _webkit_canonicalize]; |
| } |
| } |
| |
| return nil; |
| } |
| |
| - (void)_web_writeURL:(NSURL *)URL andTitle:(NSString *)title types:(NSArray *)types |
| { |
| ASSERT(URL); |
| |
| if ([title length] == 0) { |
| title = [[URL path] lastPathComponent]; |
| if ([title length] == 0) |
| title = [URL _web_userVisibleString]; |
| } |
| |
| if ([types containsObject:NSURLPboardType]) |
| [URL writeToPasteboard:self]; |
| if ([types containsObject:WebURLPboardType]) |
| [self setString:[URL _web_originalDataAsString] forType:WebURLPboardType]; |
| if ([types containsObject:WebURLNamePboardType]) |
| [self setString:title forType:WebURLNamePboardType]; |
| if ([types containsObject:NSStringPboardType]) |
| [self setString:[URL _web_userVisibleString] forType:NSStringPboardType]; |
| if ([types containsObject:WebURLsWithTitlesPboardType]) |
| [WebURLsWithTitles writeURLs:[NSArray arrayWithObject:URL] andTitles:[NSArray arrayWithObject:title] toPasteboard:self]; |
| } |
| |
| + (int)_web_setFindPasteboardString:(NSString *)string withOwner:(id)owner |
| { |
| NSPasteboard *findPasteboard = [NSPasteboard pasteboardWithName:NSFindPboard]; |
| [findPasteboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:owner]; |
| [findPasteboard setString:string forType:NSStringPboardType]; |
| return [findPasteboard changeCount]; |
| } |
| |
| - (void)_web_writeFileWrapperAsRTFDAttachment:(NSFileWrapper *)wrapper |
| { |
| NSTextAttachment *attachment = [[NSTextAttachment alloc] initWithFileWrapper:wrapper]; |
| |
| NSAttributedString *string = [NSAttributedString attributedStringWithAttachment:attachment]; |
| [attachment release]; |
| |
| NSData *RTFDData = [string RTFDFromRange:NSMakeRange(0, [string length]) documentAttributes:nil]; |
| [self setData:RTFDData forType:NSRTFDPboardType]; |
| } |
| |
| |
| - (void)_web_writePromisedRTFDFromArchive:(WebArchive*)archive containsImage:(BOOL)containsImage |
| { |
| ASSERT(archive); |
| // This image data is either the only subresource of an archive (HTML image case) |
| // or the main resource (standalone image case). |
| NSArray *subresources = [archive subresources]; |
| WebResource *resource = [archive mainResource]; |
| if (containsImage && [subresources count] > 0 |
| && MIMETypeRegistry::isSupportedImageResourceMIMEType([[subresources objectAtIndex:0] MIMEType])) |
| resource = (WebResource *)[subresources objectAtIndex:0]; |
| ASSERT(resource != nil); |
| |
| ASSERT(!containsImage || MIMETypeRegistry::isSupportedImageResourceMIMEType([resource MIMEType])); |
| if (!containsImage || MIMETypeRegistry::isSupportedImageResourceMIMEType([resource MIMEType])) |
| [self _web_writeFileWrapperAsRTFDAttachment:[resource _fileWrapperRepresentation]]; |
| |
| } |
| |
| static CachedImage* imageFromElement(DOMElement *domElement) |
| { |
| Element* element = core(domElement); |
| if (!element) |
| return 0; |
| |
| RenderObject* renderer = element->renderer(); |
| RenderImage* imageRenderer = toRenderImage(renderer); |
| if (!imageRenderer->cachedImage() || imageRenderer->cachedImage()->errorOccurred()) |
| return 0; |
| return imageRenderer->cachedImage(); |
| } |
| |
| - (void)_web_writeImage:(NSImage *)image |
| element:(DOMElement *)element |
| URL:(NSURL *)URL |
| title:(NSString *)title |
| archive:(WebArchive *)archive |
| types:(NSArray *)types |
| source:(WebHTMLView *)source |
| { |
| ASSERT(image || element); |
| ASSERT(URL); |
| |
| [self _web_writeURL:URL andTitle:title types:types]; |
| |
| if ([types containsObject:NSTIFFPboardType]) { |
| if (image) |
| [self setData:[image TIFFRepresentation] forType:NSTIFFPboardType]; |
| else if (source && element) |
| [source setPromisedDragTIFFDataSource:imageFromElement(element)]; |
| else if (element) |
| [self setData:[element _imageTIFFRepresentation] forType:NSTIFFPboardType]; |
| } |
| |
| if (archive) |
| if ([types containsObject:WebArchivePboardType]) |
| [self setData:[archive data] forType:WebArchivePboardType]; |
| else { |
| // We should not have declared types that we aren't going to write (4031826). |
| ASSERT(![types containsObject:NSRTFDPboardType]); |
| ASSERT(![types containsObject:WebArchivePboardType]); |
| } |
| } |
| |
| - (id)_web_declareAndWriteDragImageForElement:(DOMElement *)element |
| URL:(NSURL *)URL |
| title:(NSString *)title |
| archive:(WebArchive *)archive |
| source:(WebHTMLView *)source |
| { |
| ASSERT(self == [NSPasteboard pasteboardWithName:NSDragPboard]); |
| |
| NSString *extension = @""; |
| if (RenderObject* renderer = core(element)->renderer()) { |
| if (renderer->isImage()) { |
| if (CachedImage* image = toRenderImage(renderer)->cachedImage()) { |
| extension = image->image()->filenameExtension(); |
| if (![extension length]) |
| return 0; |
| } |
| } |
| } |
| |
| NSMutableArray *types = [[NSMutableArray alloc] initWithObjects:NSFilesPromisePboardType, nil]; |
| [types addObjectsFromArray:[NSPasteboard _web_writableTypesForImageIncludingArchive:(archive != nil)]]; |
| [self declareTypes:types owner:source]; |
| [self _web_writeImage:nil element:element URL:URL title:title archive:archive types:types source:source]; |
| [types release]; |
| |
| NSArray *extensions = [[NSArray alloc] initWithObjects:extension, nil]; |
| [self setPropertyList:extensions forType:NSFilesPromisePboardType]; |
| [extensions release]; |
| |
| return source; |
| } |
| |
| @end |