• 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 "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