• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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