2 WebDefaultContextMenuDelegate.m
3 Copyright 2002, Apple, Inc. All rights reserved.
6 #import <WebKit/WebDefaultContextMenuDelegate.h>
8 #import <WebKit/WebAssertions.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 #import <WebKit/WebUIDelegatePrivate.h>
24 #import <WebCore/WebCoreBridge.h>
26 #import <Foundation/NSURLConnection.h>
27 #import <Foundation/NSURLRequest.h>
28 #import <Foundation/NSURLRequestPrivate.h>
30 @implementation WebDefaultUIDelegate (WebContextMenu)
32 #ifndef OMIT_TIGER_FEATURES
33 static NSString *localizedMenuTitleFromAppKit(NSString *key, NSString *comment)
35 NSBundle *appKitBundle = [NSBundle bundleWithIdentifier:@"com.apple.AppKit"];
39 return NSLocalizedStringFromTableInBundle(key, @"MenuCommands", appKitBundle, comment);
43 - (NSMenuItem *)menuItemWithTag:(int)tag
45 NSMenuItem *menuItem = [[[NSMenuItem alloc] init] autorelease];
46 [menuItem setTag:tag];
48 NSString *title = nil;
52 case WebMenuItemTagOpenLinkInNewWindow:
53 title = UI_STRING("Open Link in New Window", "Open in New Window context menu item");
54 action = @selector(openLinkInNewWindow:);
55 [menuItem setTarget:self];
57 case WebMenuItemTagDownloadLinkToDisk:
58 title = UI_STRING("Download Linked File", "Download Linked File context menu item");
59 action = @selector(downloadLinkToDisk:);
60 [menuItem setTarget:self];
62 case WebMenuItemTagCopyLinkToClipboard:
63 title = UI_STRING("Copy Link", "Copy Link context menu item");
64 action = @selector(copyLinkToClipboard:);
65 [menuItem setTarget:self];
67 case WebMenuItemTagOpenImageInNewWindow:
68 title = UI_STRING("Open Image in New Window", "Open Image in New Window context menu item");
69 action = @selector(openImageInNewWindow:);
70 [menuItem setTarget:self];
72 case WebMenuItemTagDownloadImageToDisk:
73 title = UI_STRING("Download Image", "Download Image context menu item");
74 action = @selector(downloadImageToDisk:);
75 [menuItem setTarget:self];
77 case WebMenuItemTagCopyImageToClipboard:
78 title = UI_STRING("Copy Image", "Copy Image context menu item");
79 action = @selector(copyImageToClipboard:);
80 [menuItem setTarget:self];
82 case WebMenuItemTagOpenFrameInNewWindow:
83 title = UI_STRING("Open Frame in New Window", "Open Frame in New Window context menu item");
84 action = @selector(openFrameInNewWindow:);
85 [menuItem setTarget:self];
87 case WebMenuItemTagCopy:
88 title = UI_STRING("Copy", "Copy context menu item");
89 action = @selector(copy:);
91 case WebMenuItemTagGoBack:
92 title = UI_STRING("Back", "Back context menu item");
93 action = @selector(goBack:);
95 case WebMenuItemTagGoForward:
96 title = UI_STRING("Forward", "Forward context menu item");
97 action = @selector(goForward:);
99 case WebMenuItemTagStop:
100 title = UI_STRING("Stop", "Stop context menu item");
101 action = @selector(stopLoading:);
103 case WebMenuItemTagReload:
104 title = UI_STRING("Reload", "Reload context menu item");
105 action = @selector(reload:);
107 case WebMenuItemTagCut:
108 title = UI_STRING("Cut", "Cut context menu item");
109 action = @selector(cut:);
111 case WebMenuItemTagPaste:
112 title = UI_STRING("Paste", "Paste context menu item");
113 action = @selector(paste:);
115 case WebMenuItemTagSpellingGuess:
116 action = @selector(_changeSpellingFromMenu:);
118 case WebMenuItemTagNoGuessesFound:
119 title = UI_STRING("No Guesses Found", "No Guesses Found context menu item");
121 case WebMenuItemTagIgnoreSpelling:
122 title = UI_STRING("Ignore Spelling", "Ignore Spelling context menu item");
123 action = @selector(_ignoreSpellingFromMenu:);
125 case WebMenuItemTagLearnSpelling:
126 title = UI_STRING("Learn Spelling", "Learn Spelling context menu item");
127 action = @selector(_learnSpellingFromMenu:);
129 #ifndef OMIT_TIGER_FEATURES
130 case WebMenuItemTagSearchInSpotlight:
131 // FIXME: Perhaps move this string into WebKit directly when we're not in localization freeze
132 title = localizedMenuTitleFromAppKit(@"Search in Spotlight", @"Search in Spotlight menu title.");
133 action = @selector(_searchWithSpotlightFromMenu:);
135 case WebMenuItemTagSearchInGoogle:
136 // FIXME: Perhaps move this string into WebKit directly when we're not in localization freeze
137 title = localizedMenuTitleFromAppKit(@"Search in Google", @"Search in Google menu title.");
138 action = @selector(_searchWithGoogleFromMenu:);
146 [menuItem setTitle:title];
148 [menuItem setAction:action];
153 - (NSArray *)contextMenuItemsForElement:(NSDictionary *)element
155 NSMutableArray *menuItems = [NSMutableArray array];
157 NSURL *linkURL = [element objectForKey:WebElementLinkURLKey];
160 if([WebView _canHandleRequest:[NSURLRequest requestWithURL:linkURL]]) {
161 [menuItems addObject:[self menuItemWithTag:WebMenuItemTagOpenLinkInNewWindow]];
162 [menuItems addObject:[self menuItemWithTag:WebMenuItemTagDownloadLinkToDisk]];
164 [menuItems addObject:[self menuItemWithTag:WebMenuItemTagCopyLinkToClipboard]];
167 WebFrame *webFrame = [element objectForKey:WebElementFrameKey];
168 NSURL *imageURL = [element objectForKey:WebElementImageURLKey];
172 [menuItems addObject:[NSMenuItem separatorItem]];
174 [menuItems addObject:[self menuItemWithTag:WebMenuItemTagOpenImageInNewWindow]];
175 [menuItems addObject:[self menuItemWithTag:WebMenuItemTagDownloadImageToDisk]];
176 if ([imageURL isFileURL] || [[webFrame dataSource] _fileWrapperForURL:imageURL]) {
177 [menuItems addObject:[self menuItemWithTag:WebMenuItemTagCopyImageToClipboard]];
181 if (!imageURL && !linkURL) {
182 if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) {
183 #ifndef OMIT_TIGER_FEATURES
184 // Add Tiger-only items that act on selected text. Google search needn't be Tiger-only technically,
185 // but it's a new Tiger-only feature to have it in the context menu by default.
186 [menuItems addObject:[self menuItemWithTag:WebMenuItemTagSearchInSpotlight]];
187 [menuItems addObject:[self menuItemWithTag:WebMenuItemTagSearchInGoogle]];
188 [menuItems addObject:[NSMenuItem separatorItem]];
190 [menuItems addObject:[self menuItemWithTag:WebMenuItemTagCopy]];
192 WebView *wv = [webFrame webView];
193 if ([wv canGoBack]) {
194 [menuItems addObject:[self menuItemWithTag:WebMenuItemTagGoBack]];
196 if ([wv canGoForward]) {
197 [menuItems addObject:[self menuItemWithTag:WebMenuItemTagGoForward]];
199 if ([wv isLoading]) {
200 [menuItems addObject:[self menuItemWithTag:WebMenuItemTagStop]];
202 [menuItems addObject:[self menuItemWithTag:WebMenuItemTagReload]];
205 if (webFrame != [wv mainFrame]) {
206 [menuItems addObject:[self menuItemWithTag:WebMenuItemTagOpenFrameInNewWindow]];
211 // Attach element as the represented object to each item.
212 [menuItems makeObjectsPerformSelector:@selector(setRepresentedObject:) withObject:element];
217 - (NSArray *)editingContextMenuItemsForElement:(NSDictionary *)element
220 NSMutableArray *menuItems = [NSMutableArray array];
221 WebHTMLView *HTMLView = (WebHTMLView *)[[[element objectForKey:WebElementFrameKey] frameView] documentView];
222 ASSERT([HTMLView isKindOfClass:[WebHTMLView class]]);
224 // Add spelling related context menu items.
225 if ([HTMLView _isSelectionMisspelled]) {
226 NSArray *guesses = [HTMLView _guessesForMisspelledSelection];
227 unsigned count = [guesses count];
229 NSEnumerator *enumerator = [guesses objectEnumerator];
231 while ((guess = [enumerator nextObject]) != nil) {
232 item = [self menuItemWithTag:WebMenuItemTagSpellingGuess];
233 [item setTitle:guess];
234 [menuItems addObject:item];
237 [menuItems addObject:[self menuItemWithTag:WebMenuItemTagNoGuessesFound]];
239 [menuItems addObject:[NSMenuItem separatorItem]];
240 [menuItems addObject:[self menuItemWithTag:WebMenuItemTagIgnoreSpelling]];
241 [menuItems addObject:[self menuItemWithTag:WebMenuItemTagLearnSpelling]];
242 [menuItems addObject:[NSMenuItem separatorItem]];
245 #ifndef OMIT_TIGER_FEATURES
246 // Add Tiger-only items that aren't in our nib.
247 // FIXME: When we're not building for Panther anymore we should update the nib to include these.
248 [menuItems addObject:[self menuItemWithTag:WebMenuItemTagSearchInSpotlight]];
249 [menuItems addObject:[self menuItemWithTag:WebMenuItemTagSearchInGoogle]];
250 [menuItems addObject:[NSMenuItem separatorItem]];
253 // Load our NSTextView-like context menu nib.
254 if (defaultMenu == nil) {
255 static NSNib *textViewMenuNib = nil;
256 if (textViewMenuNib == nil) {
257 textViewMenuNib = [[NSNib alloc] initWithNibNamed:@"WebViewEditingContextMenu" bundle:[NSBundle bundleForClass:[self class]]];
259 [textViewMenuNib instantiateNibWithOwner:self topLevelObjects:nil];
262 // Add tags to the menu items because this is what the WebUIDelegate expects.
263 NSEnumerator *enumerator = [[defaultMenu itemArray] objectEnumerator];
264 while ((item = [enumerator nextObject]) != nil) {
266 SEL action = [item action];
268 if (action == @selector(cut:)) {
269 tag = WebMenuItemTagCut;
270 } else if (action == @selector(copy:)) {
271 tag = WebMenuItemTagCopy;
272 } else if (action == @selector(paste:)) {
273 tag = WebMenuItemTagPaste;
275 tag = WebMenuItemTagOther;
278 [menuItems addObject:item];
285 - (NSArray *)webView:(WebView *)wv contextMenuItemsForElement:(NSDictionary *)element defaultMenuItems:(NSArray *)defaultMenuItems
287 WebHTMLView *HTMLView = (WebHTMLView *)[[[element objectForKey:WebElementFrameKey] frameView] documentView];
288 if ([HTMLView isKindOfClass:[WebHTMLView class]] && [HTMLView _isEditable]) {
289 return [self editingContextMenuItemsForElement:element];
291 return [self contextMenuItemsForElement:element];
295 - (void)openNewWindowWithURL:(NSURL *)URL element:(NSDictionary *)element
297 WebFrame *webFrame = [element objectForKey:WebElementFrameKey];
298 WebView *webView = [webFrame webView];
300 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
301 NSString *referrer = [[webFrame _bridge] referrer];
303 [request setHTTPReferrer:referrer];
306 [webView _openNewWindowWithRequest:request];
309 - (void)downloadURL:(NSURL *)URL element:(NSDictionary *)element
311 WebFrame *webFrame = [element objectForKey:WebElementFrameKey];
312 WebView *webView = [webFrame webView];
313 [webView _downloadURL:URL];
316 - (void)openLinkInNewWindow:(id)sender
318 NSDictionary *element = [sender representedObject];
319 [self openNewWindowWithURL:[element objectForKey:WebElementLinkURLKey] element:element];
322 - (void)downloadLinkToDisk:(id)sender
324 NSDictionary *element = [sender representedObject];
325 [self downloadURL:[element objectForKey:WebElementLinkURLKey] element:element];
328 - (void)copyLinkToClipboard:(id)sender
330 NSDictionary *element = [sender representedObject];
331 NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
332 NSArray *types = [NSPasteboard _web_writableTypesForURL];
333 [pasteboard declareTypes:types owner:self];
334 [[[element objectForKey:WebElementFrameKey] webView] _writeLinkElement:element
335 withPasteboardTypes:types
336 toPasteboard:pasteboard];
339 - (void)openImageInNewWindow:(id)sender
341 NSDictionary *element = [sender representedObject];
342 [self openNewWindowWithURL:[element objectForKey:WebElementImageURLKey] element:element];
345 - (void)downloadImageToDisk:(id)sender
347 NSDictionary *element = [sender representedObject];
348 [self downloadURL:[element objectForKey:WebElementImageURLKey] element:element];
351 - (void)copyImageToClipboard:(id)sender
353 NSDictionary *element = [sender representedObject];
354 NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
355 NSArray *types = [NSPasteboard _web_writableTypesForImage];
356 [pasteboard declareTypes:types owner:self];
357 [[[element objectForKey:WebElementFrameKey] webView] _writeImageElement:element
358 withPasteboardTypes:types
359 toPasteboard:pasteboard];
362 - (void)openFrameInNewWindow:(id)sender
364 NSDictionary *element = [sender representedObject];
365 WebDataSource *dataSource = [[element objectForKey:WebElementFrameKey] dataSource];
366 NSURL *URL = [dataSource unreachableURL];
368 URL = [[dataSource request] URL];
370 [self openNewWindowWithURL:URL element:element];