f607199a9540dbfb4bcc2ddbed8166047b34ba26
[WebKit-https.git] / WebKit / Misc.subproj / WebNSPasteboardExtras.m
1 /*
2  * Copyright (C) 2005 Apple Computer, 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 <WebKit/WebNSPasteboardExtras.h>
30
31 #import <WebKit/WebArchive.h>
32 #import <WebKit/WebAssertions.h>
33 #import <WebKit/WebImageRenderer.h>
34 #import <WebKit/WebImageRendererFactory.h>
35 #import <WebKit/WebNSURLExtras.h>
36 #import <WebKit/WebResourcePrivate.h>
37 #import <WebKit/WebURLsWithTitles.h>
38 #import <WebKit/WebViewPrivate.h>
39 #import <WebKitSystemInterface.h>
40
41 #import <HIServices/CoreTranslationFlavorTypeNames.h>
42
43 NSString *WebURLPboardType = nil;
44 NSString *WebURLNamePboardType = nil;
45
46 @interface NSFilePromiseDragSource : NSObject
47 - initWithSource:(id)draggingSource;
48 - (void)setTypes:(NSArray *)types onPasteboard:(NSPasteboard *)pboard;
49 @end
50
51 @implementation NSPasteboard (WebExtras)
52
53 + (void)initialize
54 {
55     // FIXME  The code below addresses 3446192.  However we can't enable until 3446669 has been fixed.
56 #ifdef UTI_PB_API
57     CFStringRef osTypeString = UTCreateStringForOSType('url ');
58     CFStringRef utiTypeString = UTTypeCreatePreferredIdentifierForTag( kUTTagClassOSType, osTypeString, NULL );
59     WebURLPboardType = (NSString *)UTTypeCopyPreferredTagWithClass( kUTTagClassNSPboardType, utiTypeString );
60     
61     osTypeString = UTCreateStringForOSType('urln');
62     utiTypeString = UTTypeCreatePreferredIdentifierForTag( kUTTagClassOSType, osTypeString, NULL );
63     WebURLNamePboardType = (NSString *)UTTypeCopyPreferredTagWithClass( kUTTagClassNSPboardType, utiTypeString );
64 #else
65     CreatePasteboardFlavorTypeName('url ', (CFStringRef*)&WebURLPboardType);
66     CreatePasteboardFlavorTypeName('urln', (CFStringRef*)&WebURLNamePboardType);
67 #endif
68 }
69
70 + (NSArray *)_web_writableTypesForURL
71 {
72     static NSArray *types = nil;
73     if (!types) {
74         types = [[NSArray alloc] initWithObjects:
75             WebURLsWithTitlesPboardType,
76             NSURLPboardType,
77             WebURLPboardType,
78             WebURLNamePboardType,
79             NSStringPboardType,
80             nil];
81     }
82     return types;
83 }
84
85 static NSArray *_writableTypesForImageWithoutArchive (void)
86 {
87     static NSMutableArray *types = nil;
88     if (types == nil) {
89         types = [[NSMutableArray alloc] initWithObjects:NSTIFFPboardType, nil];
90         [types addObjectsFromArray:[NSPasteboard _web_writableTypesForURL]];
91     }
92     return types;
93 }
94
95 static NSArray *_writableTypesForImageWithArchive (void)
96 {
97     static NSMutableArray *types = nil;
98     if (types == nil) {
99         types = [_writableTypesForImageWithoutArchive() mutableCopy];
100         [types addObject:NSRTFDPboardType];
101         [types addObject:WebArchivePboardType];
102     }
103     return types;
104 }
105
106 + (NSArray *)_web_writableTypesForImageIncludingArchive:(BOOL)hasArchive
107 {
108     return hasArchive 
109         ? _writableTypesForImageWithArchive()
110         : _writableTypesForImageWithoutArchive();
111 }
112
113 + (NSArray *)_web_dragTypesForURL
114 {
115     return [NSArray arrayWithObjects:
116         WebURLsWithTitlesPboardType,
117         NSURLPboardType,
118         WebURLPboardType,
119         WebURLNamePboardType,
120         NSStringPboardType,
121         NSFilenamesPboardType,
122         nil];
123 }
124
125 - (NSURL *)_web_bestURL
126 {
127     NSArray *types = [self types];
128
129     if ([types containsObject:NSURLPboardType]) {
130         NSURL *URLFromPasteboard = [NSURL URLFromPasteboard:self];
131         NSString *scheme = [URLFromPasteboard scheme];
132         if ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"]) {
133             return [URLFromPasteboard _webkit_canonicalize];
134         }
135     }
136
137     if ([types containsObject:NSStringPboardType]) {
138         NSString *URLString = [self stringForType:NSStringPboardType];
139         if ([URLString _webkit_looksLikeAbsoluteURL]) {
140             NSURL *URL = [[NSURL _web_URLWithUserTypedString:URLString] _webkit_canonicalize];
141             if (URL) {
142                 return URL;
143             }
144         }
145     }
146
147     if ([types containsObject:NSFilenamesPboardType]) {
148         NSArray *files = [self propertyListForType:NSFilenamesPboardType];
149         if ([files count] == 1) {
150             NSString *file = [files objectAtIndex:0];
151             BOOL isDirectory;
152             if([[NSFileManager defaultManager] fileExistsAtPath:file isDirectory:&isDirectory] && !isDirectory){
153                 if ([WebView canShowFile:file]) {
154                     return [[NSURL fileURLWithPath:file] _webkit_canonicalize];
155                 }
156             }
157         }
158     }
159
160     return nil;
161 }
162
163 - (void)_web_writeURL:(NSURL *)URL andTitle:(NSString *)title types:(NSArray *)types
164 {
165     ASSERT(URL);
166     
167     if ([title length] == 0) {
168         title = [[URL path] lastPathComponent];
169         if ([title length] == 0) {
170             title = [URL _web_userVisibleString];
171         }
172     }
173     
174     if ([types containsObject:NSURLPboardType]) {
175         [URL writeToPasteboard:self];
176     }
177     if ([types containsObject:WebURLPboardType]) {
178         [self setString:[URL _web_userVisibleString] forType:WebURLPboardType];
179     }
180     if ([types containsObject:WebURLNamePboardType]) {
181         [self setString:title forType:WebURLNamePboardType];
182     }
183     if ([types containsObject:NSStringPboardType]) {
184         [self setString:[URL _web_userVisibleString] forType:NSStringPboardType];
185     }
186     if ([types containsObject:WebURLsWithTitlesPboardType]) {
187         [WebURLsWithTitles writeURLs:[NSArray arrayWithObject:URL] andTitles:[NSArray arrayWithObject:title] toPasteboard:self];
188     }
189 }
190
191 + (int)_web_setFindPasteboardString:(NSString *)string withOwner:(id)owner
192 {
193     NSPasteboard *findPasteboard = [NSPasteboard pasteboardWithName:NSFindPboard];
194     [findPasteboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:owner];
195     [findPasteboard setString:string forType:NSStringPboardType];
196     return [findPasteboard changeCount];
197 }
198
199 - (void)_web_writeFileWrapperAsRTFDAttachment:(NSFileWrapper *)wrapper
200 {
201     NSTextAttachment *attachment = [[NSTextAttachment alloc] initWithFileWrapper:wrapper];
202     
203     NSAttributedString *string = [NSAttributedString attributedStringWithAttachment:attachment];
204     [attachment release];
205     
206     NSData *RTFDData = [string RTFDFromRange:NSMakeRange(0, [string length]) documentAttributes:nil];
207     [self setData:RTFDData forType:NSRTFDPboardType];
208 }
209
210 - (void)_web_writeImage:(WebImageRenderer *)image 
211                     URL:(NSURL *)URL 
212                   title:(NSString *)title
213                 archive:(WebArchive *)archive
214                   types:(NSArray *)types
215 {
216     ASSERT(image);
217     ASSERT(URL);
218
219     [self _web_writeURL:URL andTitle:title types:types];
220     
221     if ([types containsObject:NSTIFFPboardType]) {
222         [self setData:[image TIFFRepresentation] forType:NSTIFFPboardType];
223     }
224     
225     if (archive) {
226         if ([types containsObject:NSRTFDPboardType]) {
227             // This image data is either the only subresource of an archive (HTML image case)
228             // or the main resource (standalone image case).
229             NSArray *subresources = [archive subresources];
230             WebResource *resource = [subresources count] > 0 ? [subresources objectAtIndex:0] : [archive mainResource];
231             ASSERT(resource != nil);
232             
233             ASSERT([[[WebImageRendererFactory sharedFactory] supportedMIMETypes] containsObject:[resource MIMEType]]);
234             [self _web_writeFileWrapperAsRTFDAttachment:[resource _fileWrapperRepresentation]];
235         }
236         if ([types containsObject:WebArchivePboardType]) {
237             [self setData:[archive data] forType:WebArchivePboardType];
238         }
239     } else {
240         // We should not have declared types that we aren't going to write (4031826).
241         ASSERT(![types containsObject:NSRTFDPboardType]);
242         ASSERT(![types containsObject:WebArchivePboardType]);
243     }
244 }
245
246 - (id)_web_declareAndWriteDragImage:(WebImageRenderer *)image 
247                                 URL:(NSURL *)URL 
248                               title:(NSString *)title
249                             archive:(WebArchive *)archive
250                              source:(id)source
251 {
252     ASSERT(self == [NSPasteboard pasteboardWithName:NSDragPboard]);
253     NSMutableArray *types = [[NSMutableArray alloc] initWithObjects:NSFilesPromisePboardType, nil];
254     [types addObjectsFromArray:[NSPasteboard _web_writableTypesForImageIncludingArchive:(archive != nil)]];
255     [self declareTypes:types owner:source];    
256     [self _web_writeImage:image URL:URL title:title archive:archive types:types];
257     [types release];
258     
259     NSString *extension = WKGetPreferredExtensionForMIMEType([image MIMEType]);
260     if (extension == nil) {
261         extension = @"";
262     }
263     NSArray *extensions = [NSArray arrayWithObject:extension];
264     
265 #ifdef OMIT_TIGER_FEATURES
266     id dragSource = [[NSFilePromiseDragSource alloc] initWithSource:source];
267     [dragSource setTypes:extensions onPasteboard:self];
268     return dragSource;
269 #else
270     [self setPropertyList:extensions forType:NSFilesPromisePboardType];
271     return source;
272 #endif
273 }
274
275 @end