8b2118d1e1706c6784e5b9775b201f29d63a36da
[WebKit-https.git] / WebKit / WebView.subproj / WebDefaultContextMenuDelegate.m
1 /*
2       WebDefaultContextMenuDelegate.m
3       Copyright 2002, Apple, Inc. All rights reserved.
4 */
5
6 #import <WebKit/WebDefaultContextMenuDelegate.h>
7
8 #import <WebKit/WebAssertions.h>
9 #import <WebKit/DOM.h>
10 #import <WebKit/WebBridge.h>
11 #import <WebKit/WebDataSourcePrivate.h>
12 #import <WebKit/WebDefaultUIDelegate.h>
13 #import <WebKit/WebDOMOperations.h>
14 #import <WebKit/WebFramePrivate.h>
15 #import <WebKit/WebHTMLViewPrivate.h>
16 #import <WebKit/WebLocalizableStrings.h>
17 #import <WebKit/WebNSPasteboardExtras.h>
18 #import <WebKit/WebFrameView.h>
19 #import <WebKit/WebPolicyDelegate.h>
20 #import <WebKit/WebViewPrivate.h>
21 #import <WebKit/WebUIDelegate.h>
22
23 #import <WebCore/WebCoreBridge.h>
24
25 #import <Foundation/NSURLConnection.h>
26 #import <Foundation/NSURLRequest.h>
27 #import <Foundation/NSURLRequestPrivate.h>
28
29 @implementation WebDefaultUIDelegate (WebContextMenu)
30
31 - (NSMenuItem *)menuItemWithTag:(int)tag
32 {
33     NSMenuItem *menuItem = [[[NSMenuItem alloc] init] autorelease];
34     [menuItem setTag:tag];
35     
36     NSString *title = nil;
37     SEL action = NULL;
38     
39     switch(tag) {
40         case WebMenuItemTagOpenLinkInNewWindow:
41             title = UI_STRING("Open Link in New Window", "Open in New Window context menu item");
42             action = @selector(openLinkInNewWindow:);
43             [menuItem setTarget:self];
44             break;
45         case WebMenuItemTagDownloadLinkToDisk:
46             title = UI_STRING("Download Linked File", "Download Linked File context menu item");
47             action = @selector(downloadLinkToDisk:);
48             [menuItem setTarget:self];
49             break;
50         case WebMenuItemTagCopyLinkToClipboard:
51             title = UI_STRING("Copy Link", "Copy Link context menu item");
52             action = @selector(copyLinkToClipboard:);
53             [menuItem setTarget:self];
54             break;
55         case WebMenuItemTagOpenImageInNewWindow:
56             title = UI_STRING("Open Image in New Window", "Open Image in New Window context menu item");
57             action = @selector(openImageInNewWindow:);
58             [menuItem setTarget:self];
59             break;
60         case WebMenuItemTagDownloadImageToDisk:
61             title = UI_STRING("Download Image", "Download Image context menu item");
62             action = @selector(downloadImageToDisk:);
63             [menuItem setTarget:self];
64             break;
65         case WebMenuItemTagCopyImageToClipboard:
66             title = UI_STRING("Copy Image", "Copy Image context menu item");
67             action = @selector(copyImageToClipboard:);
68             [menuItem setTarget:self];
69             break;
70         case WebMenuItemTagOpenFrameInNewWindow:
71             title = UI_STRING("Open Frame in New Window", "Open Frame in New Window context menu item");
72             action = @selector(openFrameInNewWindow:);
73             [menuItem setTarget:self];
74             break;
75         case WebMenuItemTagCopy:
76             title = UI_STRING("Copy", "Copy context menu item");
77             action = @selector(copy:);
78             break;
79         case WebMenuItemTagGoBack:
80             title = UI_STRING("Back", "Back context menu item");
81             action = @selector(goBack:);
82             break;
83         case WebMenuItemTagGoForward:
84             title = UI_STRING("Forward", "Forward context menu item");
85             action = @selector(goForward:);
86             break;
87         case WebMenuItemTagStop:
88             title = UI_STRING("Stop", "Stop context menu item");
89             action = @selector(stopLoading:);
90             break;
91         case WebMenuItemTagReload:
92             title = UI_STRING("Reload", "Reload context menu item");
93             action = @selector(reload:);
94             break;
95         case WebMenuItemTagCut:
96             title = UI_STRING("Cut", "Cut context menu item");
97             action = @selector(cut:);
98             break;
99         case WebMenuItemTagPaste:
100             title = UI_STRING("Paste", "Paste context menu item");
101             action = @selector(paste:);
102             break;
103         case WebMenuItemTagSpellingGuess:
104             action = @selector(_changeSpellingFromMenu:);
105             break;
106         case WebMenuItemTagNoGuessesFound:
107             title = UI_STRING("No Guesses Found", "No Guesses Found context menu item");
108             break;
109         case WebMenuItemTagIgnoreSpelling:
110             title = UI_STRING("Ignore Spelling", "Ignore Spelling context menu item");
111             action = @selector(_ignoreSpellingFromMenu:);
112             break;
113         case WebMenuItemTagLearnSpelling:
114             title = UI_STRING("Learn Spelling", "Learn Spelling context menu item");
115             action = @selector(_learnSpellingFromMenu:);
116             break;
117         default:
118             return nil;
119     }
120
121     if (title != nil) {
122         [menuItem setTitle:title];
123     }
124     [menuItem setAction:action];
125     
126     return menuItem;
127 }
128
129 - (NSArray *)contextMenuItemsForElement:(NSDictionary *)element
130 {
131     NSMutableArray *menuItems = [NSMutableArray array];
132     
133     NSURL *linkURL = [element objectForKey:WebElementLinkURLKey];
134     
135     if (linkURL) {
136         if([WebView _canHandleRequest:[NSURLRequest requestWithURL:linkURL]]) {
137             [menuItems addObject:[self menuItemWithTag:WebMenuItemTagOpenLinkInNewWindow]];
138             [menuItems addObject:[self menuItemWithTag:WebMenuItemTagDownloadLinkToDisk]];
139         }
140         [menuItems addObject:[self menuItemWithTag:WebMenuItemTagCopyLinkToClipboard]];
141     }
142     
143     WebFrame *webFrame = [element objectForKey:WebElementFrameKey];
144     NSURL *imageURL = [element objectForKey:WebElementImageURLKey];
145     
146     if (imageURL) {
147         if (linkURL) {
148             [menuItems addObject:[NSMenuItem separatorItem]];
149         }
150         [menuItems addObject:[self menuItemWithTag:WebMenuItemTagOpenImageInNewWindow]];
151         [menuItems addObject:[self menuItemWithTag:WebMenuItemTagDownloadImageToDisk]];
152         if ([imageURL isFileURL] || [[webFrame dataSource] _fileWrapperForURL:imageURL]) {
153             [menuItems addObject:[self menuItemWithTag:WebMenuItemTagCopyImageToClipboard]];
154         }
155     }
156     
157     if (!imageURL && !linkURL) {
158         if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
159             [menuItems addObject:[self menuItemWithTag:WebMenuItemTagCopy]];
160         } else {
161             WebView *wv = [webFrame webView];
162             if ([wv canGoBack]) {
163                 [menuItems addObject:[self menuItemWithTag:WebMenuItemTagGoBack]];
164             }
165             if ([wv canGoForward]) {
166                 [menuItems addObject:[self menuItemWithTag:WebMenuItemTagGoForward]];
167             }
168             if ([wv isLoading]) {
169                 [menuItems addObject:[self menuItemWithTag:WebMenuItemTagStop]];
170             } else {
171                 [menuItems addObject:[self menuItemWithTag:WebMenuItemTagReload]];
172             }
173             
174             if (webFrame != [wv mainFrame]) {
175                 [menuItems addObject:[self menuItemWithTag:WebMenuItemTagOpenFrameInNewWindow]];
176             }
177         }
178     }
179     
180     // Attach element as the represented object to each item.
181     [menuItems makeObjectsPerformSelector:@selector(setRepresentedObject:) withObject:element];
182     
183     return menuItems;
184 }
185
186 - (NSArray *)editingContextMenuItemsForElement:(NSDictionary *)element
187 {
188     NSMenuItem *item;
189     NSMutableArray *menuItems = [NSMutableArray array];
190     WebHTMLView *HTMLView = (WebHTMLView *)[[[element objectForKey:WebElementFrameKey] frameView] documentView];
191     ASSERT([HTMLView isKindOfClass:[WebHTMLView class]]);
192     
193     // Add spelling related context menu items.
194     if ([HTMLView _isSelectionMisspelled]) {
195         NSArray *guesses = [HTMLView _guessesForMisspelledSelection];
196         unsigned count = [guesses count];
197         if (count > 0) {
198             NSEnumerator *enumerator = [guesses objectEnumerator];
199             NSString *guess;
200             while ((guess = [enumerator nextObject]) != nil) {
201                 item = [self menuItemWithTag:WebMenuItemTagSpellingGuess];
202                 [item setTitle:guess];
203                 [menuItems addObject:item];
204             }
205         } else {
206             [menuItems addObject:[self menuItemWithTag:WebMenuItemTagNoGuessesFound]];
207         }
208         [menuItems addObject:[NSMenuItem separatorItem]];
209         [menuItems addObject:[self menuItemWithTag:WebMenuItemTagIgnoreSpelling]];
210         [menuItems addObject:[self menuItemWithTag:WebMenuItemTagLearnSpelling]];
211         [menuItems addObject:[NSMenuItem separatorItem]];
212     }
213     
214     // Load our NSTextView-like context menu nib.
215     if (defaultMenu == nil) {
216         static NSNib *textViewMenuNib = nil;
217         if (textViewMenuNib == nil) {
218             textViewMenuNib = [[NSNib alloc] initWithNibNamed:@"WebViewEditingContextMenu" bundle:[NSBundle bundleForClass:[self class]]];
219         }
220         [textViewMenuNib instantiateNibWithOwner:self topLevelObjects:nil];
221     }
222     
223     // Add tags to the menu items because this is what the WebUIDelegate expects.
224     NSEnumerator *enumerator = [[defaultMenu itemArray] objectEnumerator];
225     while ((item = [enumerator nextObject]) != nil) {
226         item = [item copy];
227         SEL action = [item action];
228         int tag;
229         if (action == @selector(cut:)) {
230             tag = WebMenuItemTagCut;
231         } else if (action == @selector(copy:)) {
232             tag = WebMenuItemTagCopy;
233         } else if (action == @selector(paste:)) {
234             tag = WebMenuItemTagPaste;
235         } else {
236             tag = WebMenuItemTagOther;
237         }
238         [item setTag:tag];
239         [menuItems addObject:item];
240         [item release];
241     }
242     
243     return menuItems;
244 }
245
246 - (NSArray *)webView:(WebView *)wv contextMenuItemsForElement:(NSDictionary *)element  defaultMenuItems:(NSArray *)defaultMenuItems
247 {
248     WebHTMLView *HTMLView = (WebHTMLView *)[[[element objectForKey:WebElementFrameKey] frameView] documentView];
249     if ([HTMLView isKindOfClass:[WebHTMLView class]] && [HTMLView _isEditable]) {
250         return [self editingContextMenuItemsForElement:element];
251     } else {
252         return [self contextMenuItemsForElement:element];
253     }
254 }
255
256 - (void)openNewWindowWithURL:(NSURL *)URL element:(NSDictionary *)element
257 {
258     WebFrame *webFrame = [element objectForKey:WebElementFrameKey];
259     WebView *webView = [webFrame webView];
260     
261     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
262     NSString *referrer = [[webFrame _bridge] referrer];
263     if (referrer) {
264         [request setHTTPReferrer:referrer];
265     }
266     
267     [webView _openNewWindowWithRequest:request];
268 }
269
270 - (void)downloadURL:(NSURL *)URL element:(NSDictionary *)element
271 {
272     WebFrame *webFrame = [element objectForKey:WebElementFrameKey];
273     WebView *webView = [webFrame webView];
274     [webView _downloadURL:URL];
275 }
276
277 - (void)openLinkInNewWindow:(id)sender
278 {
279     NSDictionary *element = [sender representedObject];
280     [self openNewWindowWithURL:[element objectForKey:WebElementLinkURLKey] element:element];
281 }
282
283 - (void)downloadLinkToDisk:(id)sender
284 {
285     NSDictionary *element = [sender representedObject];
286     [self downloadURL:[element objectForKey:WebElementLinkURLKey] element:element];
287 }
288
289 - (void)copyLinkToClipboard:(id)sender
290 {
291     NSDictionary *element = [sender representedObject];
292     NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
293     NSArray *types = [NSPasteboard _web_writableTypesForURL];
294     [pasteboard declareTypes:types owner:self];    
295     [[[element objectForKey:WebElementFrameKey] webView] _writeLinkElement:element 
296                                                        withPasteboardTypes:types
297                                                               toPasteboard:pasteboard];
298 }
299
300 - (void)openImageInNewWindow:(id)sender
301 {
302     NSDictionary *element = [sender representedObject];
303     [self openNewWindowWithURL:[element objectForKey:WebElementImageURLKey] element:element];
304 }
305
306 - (void)downloadImageToDisk:(id)sender
307 {
308     NSDictionary *element = [sender representedObject];
309     [self downloadURL:[element objectForKey:WebElementImageURLKey] element:element];
310 }
311
312 - (void)copyImageToClipboard:(id)sender
313 {
314     NSDictionary *element = [sender representedObject];
315     NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
316     NSArray *types = [NSPasteboard _web_writableTypesForImage];
317     [pasteboard declareTypes:types owner:self];
318     [[[element objectForKey:WebElementFrameKey] webView] _writeImageElement:element 
319                                                         withPasteboardTypes:types 
320                                                                toPasteboard:pasteboard];
321 }
322
323 - (void)openFrameInNewWindow:(id)sender
324 {
325     NSDictionary *element = [sender representedObject];
326     WebDataSource *dataSource = [[element objectForKey:WebElementFrameKey] dataSource];
327     NSURL *URL = [dataSource unreachableURL];
328     if (URL == nil) {
329         URL = [[dataSource request] URL];
330     }    
331     [self openNewWindowWithURL:URL element:element];
332 }
333
334 @end