96a7c607ea0a68bd7ad984450b15380e57de3b08
[WebKit-https.git] / WebKit / WebCoreSupport.subproj / WebBridge.m
1 /*      
2     WebBridge.m
3     Copyright (c) 2002, 2003, Apple Computer, Inc. All rights reserved.
4 */
5
6 #import <WebKit/WebBridge.h>
7
8 #import <WebKit/WebAssertions.h>
9 #import <WebKit/WebBackForwardList.h>
10 #import <WebKit/WebBaseNetscapePluginView.h>
11 #import <WebKit/WebBasePluginPackage.h>
12 #import <WebKit/WebBaseResourceHandleDelegate.h>
13 #import <WebKit/WebDataSourcePrivate.h>
14 #import <WebKit/WebDefaultResourceLoadDelegate.h>
15 #import <WebKit/WebDefaultUIDelegate.h>
16 #import <WebKit/WebEditingDelegate.h>
17 #import <WebKit/WebFileButton.h>
18 #import <WebKit/WebFormDelegate.h>
19 #import <WebKit/WebFramePrivate.h>
20 #import <WebKit/WebFrameViewPrivate.h>
21 #import <WebKit/WebHistoryItemPrivate.h>
22 #import <WebKit/WebHTMLRepresentationPrivate.h>
23 #import <WebKit/WebHTMLViewPrivate.h>
24 #import <WebKit/WebJavaScriptTextInputPanel.h>
25 #import <WebKit/WebKitErrorsPrivate.h>
26 #import <WebKit/WebKitLogging.h>
27 #import <WebKit/WebKitStatisticsPrivate.h>
28 #import <WebKit/WebKitSystemBits.h>
29 #import <WebKit/WebNetscapePluginEmbeddedView.h>
30 #import <WebKit/WebNetscapePluginPackage.h>
31 #import <WebKit/WebNSURLExtras.h>
32 #import <WebKit/WebNullPluginView.h>
33 #import <WebKit/WebPlugin.h>
34 #import <WebKit/WebPluginController.h>
35 #import <WebKit/WebPluginDatabase.h>
36 #import <WebKit/WebPluginPackage.h>
37 #import <WebKit/WebPluginViewFactory.h>
38 #import <WebKit/WebNetscapePluginDocumentView.h>
39 #import <WebKit/WebPreferencesPrivate.h>
40 #import <WebKit/WebResourceLoadDelegate.h>
41 #import <WebKit/WebSubresourceClient.h>
42 #import <WebKit/WebViewInternal.h>
43 #import <WebKit/WebViewPrivate.h>
44 #import <WebKit/WebUIDelegatePrivate.h>
45
46 #import <Foundation/NSURLRequest.h>
47 #import <Foundation/NSURLRequestPrivate.h>
48 #import <Foundation/NSString_NSURLExtras.h>
49 #import <Foundation/NSDictionary_NSURLExtras.h>
50 #import <Foundation/NSURLConnection.h>
51 #import <Foundation/NSURLResponse.h>
52 #import <Foundation/NSURLResponsePrivate.h>
53 #import <Foundation/NSURLFileTypeMappings.h>
54
55 #import <WebKit/WebLocalizableStrings.h>
56
57 #import <JavaVM/jni.h>
58
59 #define KeyboardUIModeDidChangeNotification @"com.apple.KeyboardUIModeDidChange"
60 #define AppleKeyboardUIMode CFSTR("AppleKeyboardUIMode")
61 #define UniversalAccessDomain CFSTR("com.apple.universalaccess")
62
63 // For compatibility only with old SPI. 
64 @interface NSObject (OldWebPlugin)
65 - (void)setIsSelected:(BOOL)f;
66 @end
67
68 @interface NSApplication (DeclarationStolenFromAppKit)
69 - (void)_cycleWindowsReversed:(BOOL)reversed;
70 @end
71
72 @interface NSView (AppKitSecretsWebBridgeKnowsAbout)
73 - (NSView *)_findLastViewInKeyViewLoop;
74 @end
75
76 @interface NSURLResponse (FoundationSecretsWebBridgeKnowsAbout)
77 - (NSTimeInterval)_calculatedExpiration;
78 @end
79
80 @interface NSView (JavaPluginSecrets)
81 - (jobject)pollForAppletInWindow: (NSWindow *)window;
82 @end
83
84 // For compatibility only.
85 @interface NSObject (OldPluginAPI)
86 + (NSView <WebPlugin> *)pluginViewWithArguments:(NSDictionary *)arguments;
87 @end
88
89 NSString *WebPluginBaseURLKey =     @"WebPluginBaseURL";
90 NSString *WebPluginAttributesKey =  @"WebPluginAttributes";
91 NSString *WebPluginContainerKey =   @"WebPluginContainer";
92
93 @implementation WebBridge
94
95 - (id)initWithWebFrame:(WebFrame *)webFrame
96 {
97     self = [super init];
98
99     ++WebBridgeCount;
100     
101     WebView *webView = [webFrame webView];
102     
103     // Non-retained because data source owns representation owns bridge.
104     // But WebFrame will call close on us before it goes away, which
105     // guarantees we will not have a stale reference.
106     _frame = webFrame;
107
108     [self setName:[webFrame name]];
109     [self initializeSettings:[webView _settings]];
110     [self setTextSizeMultiplier:[webView textSizeMultiplier]];
111
112     return self;
113 }
114
115 - (void)dealloc
116 {
117     ASSERT(_frame == nil);
118
119     if (_keyboardUIModeAccessed) {
120         [[NSDistributedNotificationCenter defaultCenter] 
121             removeObserver:self name:KeyboardUIModeDidChangeNotification object:nil];
122         [[NSNotificationCenter defaultCenter] 
123             removeObserver:self name:WebPreferencesChangedNotification object:nil];
124     }
125     
126     --WebBridgeCount;
127     
128     [super dealloc];
129 }
130
131 - (WebFrame *)webFrame
132 {
133     return _frame;
134 }
135
136 - (NSArray *)childFrames
137 {
138     ASSERT(_frame != nil);
139     NSArray *frames = [_frame childFrames];
140     NSEnumerator *e = [frames objectEnumerator];
141     NSMutableArray *frameBridges = [NSMutableArray arrayWithCapacity:[frames count]];
142     WebFrame *childFrame;
143     while ((childFrame = [e nextObject])) {
144         id frameBridge = [childFrame _bridge];
145         if (frameBridge)
146             [frameBridges addObject:frameBridge];
147     }
148     return frameBridges;
149 }
150
151 - (WebCoreBridge *)mainFrame
152 {
153     ASSERT(_frame != nil);
154     return [[[_frame webView] mainFrame] _bridge];
155 }
156
157 - (WebCoreBridge *)findFrameNamed:(NSString *)name;
158 {
159     ASSERT(_frame != nil);
160     return [[_frame findFrameNamed:name] _bridge];
161 }
162
163 - (NSView *)documentView
164 {
165     ASSERT(_frame != nil);
166     return [[_frame frameView] documentView];
167 }
168
169 - (WebCoreBridge *)createWindowWithURL:(NSURL *)URL frameName:(NSString *)name
170 {
171     ASSERT(_frame != nil);
172
173     NSMutableURLRequest *request = nil;
174
175     if (URL != nil && ![URL _web_isEmpty]) {
176         request = [NSMutableURLRequest requestWithURL:URL];
177         [request setHTTPReferrer:[self referrer]];
178     }
179
180     WebView *currentWebView = [_frame webView];
181     id wd = [currentWebView UIDelegate];
182     WebView *newWebView = nil;
183     
184     if ([wd respondsToSelector:@selector(webView:createWebViewWithRequest:)])
185         newWebView = [wd webView:currentWebView createWebViewWithRequest:request];
186     else
187         newWebView = [[WebDefaultUIDelegate sharedUIDelegate] webView:currentWebView createWebViewWithRequest:request];
188     [newWebView _setTopLevelFrameName:name];
189     return [[newWebView mainFrame] _bridge];
190 }
191
192 - (void)showWindow
193 {
194     WebView *wv = [_frame webView];
195     [[wv _UIDelegateForwarder] webViewShow: wv];
196 }
197
198 - (BOOL)areToolbarsVisible
199 {
200     ASSERT(_frame != nil);
201     WebView *wv = [_frame webView];
202     id wd = [wv UIDelegate];
203     if ([wd respondsToSelector: @selector(webViewAreToolbarsVisible:)])
204         return [wd webViewAreToolbarsVisible: wv];
205     return [[WebDefaultUIDelegate sharedUIDelegate] webViewAreToolbarsVisible:wv];
206 }
207
208 - (void)setToolbarsVisible:(BOOL)visible
209 {
210     ASSERT(_frame != nil);
211     WebView *wv = [_frame webView];
212     [[wv _UIDelegateForwarder] webView:wv setToolbarsVisible:visible];
213 }
214
215 - (BOOL)areScrollbarsVisible
216 {
217     ASSERT(_frame != nil);
218     return [[_frame frameView] allowsScrolling];
219 }
220
221 - (void)setScrollbarsVisible:(BOOL)visible
222 {
223     ASSERT(_frame != nil);
224     [[_frame frameView] setAllowsScrolling:visible];
225 }
226
227 - (BOOL)isStatusBarVisible
228 {
229     ASSERT(_frame != nil);
230     WebView *wv = [_frame webView];
231     id wd = [wv UIDelegate];
232     if ([wd respondsToSelector: @selector(webViewIsStatusBarVisible:)])
233         return [wd webViewIsStatusBarVisible:wv];
234     return [[WebDefaultUIDelegate sharedUIDelegate] webViewIsStatusBarVisible:wv];
235 }
236
237 - (void)setStatusBarVisible:(BOOL)visible
238 {
239     ASSERT(_frame != nil);
240     WebView *wv = [_frame webView];
241     [[wv _UIDelegateForwarder] webView:wv setStatusBarVisible:visible];
242 }
243
244 - (void)setWindowFrame:(NSRect)frameRect
245 {
246     ASSERT(_frame != nil);
247     WebView *webView = [_frame webView];
248     [[webView _UIDelegateForwarder] webView:webView setFrame:frameRect];
249 }
250
251 - (NSRect)windowFrame
252 {
253     ASSERT(_frame != nil);
254     WebView *webView = [_frame webView];
255     return [[webView _UIDelegateForwarder] webViewFrame:webView];
256 }
257
258 - (void)setWindowContentRect:(NSRect)contentRect
259 {
260     ASSERT(_frame != nil);
261     WebView *webView = [_frame webView];
262     [[webView _UIDelegateForwarder] webView:webView setFrame:contentRect];
263 }
264
265 - (NSRect)windowContentRect
266 {
267     ASSERT(_frame != nil);
268     WebView *webView = [_frame webView];
269     return [[webView _UIDelegateForwarder] webViewContentRect:webView];
270 }
271
272 - (void)setWindowIsResizable:(BOOL)resizable
273 {
274     ASSERT(_frame != nil);
275     WebView *webView = [_frame webView];
276     [[webView _UIDelegateForwarder] webView:webView setResizable:resizable];
277 }
278
279 - (BOOL)windowIsResizable
280 {
281     ASSERT(_frame != nil);
282     WebView *webView = [_frame webView];
283     return [[webView _UIDelegateForwarder] webViewIsResizable:webView];
284 }
285
286 - (NSResponder *)firstResponder
287 {
288     ASSERT(_frame != nil);
289     WebView *webView = [_frame webView];
290     return [[webView _UIDelegateForwarder] webViewFirstResponder:webView];
291 }
292
293 - (void)makeFirstResponder:(NSResponder *)view
294 {
295     ASSERT(_frame != nil);
296     WebView *webView = [_frame webView];
297     [webView _pushPerformingProgrammaticFocus];
298     [[webView _UIDelegateForwarder] webView:webView makeFirstResponder:view];
299     [webView _popPerformingProgrammaticFocus];
300 }
301
302 - (void)closeWindowSoon
303 {
304     [[_frame webView] performSelector:@selector(_closeWindow) withObject:nil afterDelay:0.0];
305 }
306
307 - (NSWindow *)window
308 {
309     ASSERT(_frame != nil);
310     return [[_frame frameView] window];
311 }
312
313 - (void)runJavaScriptAlertPanelWithMessage:(NSString *)message
314 {
315     WebView *wv = [_frame webView];
316     [[wv _UIDelegateForwarder] webView:wv runJavaScriptAlertPanelWithMessage:message];
317 }
318
319 - (BOOL)runJavaScriptConfirmPanelWithMessage:(NSString *)message
320 {
321     WebView *wv = [_frame webView];
322     id wd = [wv UIDelegate];
323     if ([wd respondsToSelector: @selector(webView:runJavaScriptConfirmPanelWithMessage:)])
324         return [wd webView:wv runJavaScriptConfirmPanelWithMessage:message];
325     return [[WebDefaultUIDelegate sharedUIDelegate] webView:wv runJavaScriptConfirmPanelWithMessage:message];
326 }
327
328 - (BOOL)runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText returningText:(NSString **)result
329 {
330     WebView *wv = [_frame webView];
331     id wd = [wv UIDelegate];
332     if ([wd respondsToSelector: @selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:)])
333         *result = [wd webView:wv runJavaScriptTextInputPanelWithPrompt:prompt defaultText:defaultText];
334     else
335         *result = [[WebDefaultUIDelegate sharedUIDelegate] webView:wv runJavaScriptTextInputPanelWithPrompt:prompt defaultText:defaultText];
336     return *result != nil;
337 }
338
339 - (NSView <WebCoreFileButton> *)fileButtonWithDelegate:(id <WebCoreFileButtonDelegate>)delegate
340 {
341     return [[WebFileButton alloc] initWithBridge:self delegate:delegate];
342 }
343
344 - (void)runOpenPanelForFileButtonWithResultListener:(id<WebOpenPanelResultListener>)resultListener
345 {
346     WebView *wv = [_frame webView];
347     [[wv _UIDelegateForwarder] webView:wv runOpenPanelForFileButtonWithResultListener:resultListener];
348 }
349
350
351 - (WebDataSource *)dataSource
352 {
353     ASSERT(_frame != nil);
354     WebDataSource *dataSource = [_frame dataSource];
355
356     ASSERT(dataSource != nil);
357     ASSERT([dataSource _isCommitted]);
358
359     return dataSource;
360 }
361
362 - (void)setTitle:(NSString *)title
363 {
364     [[self dataSource] _setTitle:[title _web_stringByCollapsingNonPrintingCharacters]];
365 }
366
367 - (void)setStatusText:(NSString *)status
368 {
369     ASSERT(_frame != nil);
370     WebView *wv = [_frame webView];
371     [[wv _UIDelegateForwarder] webView:wv setStatusText:status];
372 }
373
374 - (void)receivedData:(NSData *)data textEncodingName:(NSString *)textEncodingName
375 {
376     // Set the encoding. This only needs to be done once, but it's harmless to do it again later.
377     NSString *encoding = [[self dataSource] _overrideEncoding];
378     BOOL userChosen = encoding != nil;
379     if (encoding == nil) {
380         encoding = textEncodingName;
381     }
382     [self setEncoding:encoding userChosen:userChosen];
383
384     [self addData:data];
385 }
386
387 - (id <WebCoreResourceHandle>)startLoadingResource:(id <WebCoreResourceLoader>)resourceLoader withURL:(NSURL *)URL customHeaders:(NSDictionary *)customHeaders
388 {
389     // If we are no longer attached to a WebView, this must be an attempted load from an
390     // onUnload handler, so let's just block it.
391     if ([[self dataSource] _webView] == nil) {
392         return nil;
393     }
394
395     return [WebSubresourceClient startLoadingResource:resourceLoader
396                                               withURL:URL
397                                         customHeaders:customHeaders
398                                              referrer:[self referrer]
399                                         forDataSource:[self dataSource]];
400 }
401
402 - (id <WebCoreResourceHandle>)startLoadingResource:(id <WebCoreResourceLoader>)resourceLoader withURL:(NSURL *)URL customHeaders:(NSDictionary *)customHeaders postData:(NSData *)data
403 {
404     // If we are no longer attached to a WebView, this must be an attempted load from an
405     // onUnload handler, so let's just block it.
406     if ([[self dataSource] _webView] == nil) {
407         return nil;
408     }
409
410     return [WebSubresourceClient startLoadingResource:resourceLoader
411                                               withURL:URL
412                                         customHeaders:customHeaders
413                                              postData:data
414                                              referrer:[self referrer]
415                                         forDataSource:[self dataSource]];
416 }
417
418 - (void)objectLoadedFromCacheWithURL:(NSURL *)URL response: response size:(unsigned)bytes
419 {
420     ASSERT(_frame != nil);
421     ASSERT(response != nil);
422
423     NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL];
424     WebView *wv = [_frame webView];
425     id delegate = [wv resourceLoadDelegate];
426     id sharedDelegate = [WebDefaultResourceLoadDelegate sharedResourceLoadDelegate];
427     id identifier;
428     WebResourceDelegateImplementationCache implementations = [wv _resourceLoadDelegateImplementations];
429     
430     // No chance for delegate to modify request, so we don't send a willSendRequest:redirectResponse: message.
431     if (implementations.delegateImplementsIdentifierForRequest)
432         identifier = [delegate webView:wv identifierForInitialRequest: request fromDataSource: [self dataSource]];
433     else
434         identifier = [sharedDelegate webView:wv identifierForInitialRequest:request fromDataSource:[self dataSource]];
435     
436     if (implementations.delegateImplementsDidReceiveResponse)
437         [delegate webView:wv resource: identifier didReceiveResponse: response fromDataSource: [self dataSource]];
438     else
439         [sharedDelegate webView:wv resource: identifier didReceiveResponse: response fromDataSource: [self dataSource]];
440
441     if (implementations.delegateImplementsDidReceiveContentLength)
442         [delegate webView:wv resource: identifier didReceiveContentLength: bytes fromDataSource: [self dataSource]];
443     else
444         [sharedDelegate webView:wv resource: identifier didReceiveContentLength: bytes fromDataSource: [self dataSource]];
445
446     if (implementations.delegateImplementsDidFinishLoadingFromDataSource)
447         [delegate webView:wv resource: identifier didFinishLoadingFromDataSource: [self dataSource]];
448     else
449         [sharedDelegate webView:wv resource: identifier didFinishLoadingFromDataSource: [self dataSource]];
450     
451     [[_frame webView] _finishedLoadingResourceFromDataSource:[self dataSource]];
452
453     [request release];
454 }
455
456 - (NSData *)syncLoadResourceWithURL:(NSURL *)URL customHeaders:(NSDictionary *)requestHeaders postData:(NSData *)postData finalURL:(NSURL **)finalURL responseHeaders:(NSDictionary **)responseHeaderDict statusCode:(int *)statusCode
457 {
458     NSMutableURLRequest *newRequest = [[NSMutableURLRequest alloc] initWithURL:URL];
459
460     if (postData) {
461         [newRequest setHTTPMethod:@"POST"];
462         [newRequest setHTTPBody:postData];
463     }
464
465     NSEnumerator *e = [requestHeaders keyEnumerator];
466     NSString *key;
467     while ((key = (NSString *)[e nextObject]) != nil) {
468         [newRequest addValue:[requestHeaders objectForKey:key] forHTTPHeaderField:key];
469     }
470     
471     // Never use cached data for these requests (xmlhttprequests).
472     [newRequest setCachePolicy:[[[self dataSource] request] cachePolicy]];
473     [newRequest setHTTPReferrer:[self referrer]];
474     
475     WebView *webView = [_frame webView];
476     [newRequest setMainDocumentURL:[[[[webView mainFrame] dataSource] request] URL]];
477     [newRequest setHTTPUserAgent:[webView userAgentForURL:[newRequest URL]]];
478
479     NSURLResponse *response = nil;
480     NSError *error = nil;
481     NSData *result = [NSURLConnection sendSynchronousRequest:newRequest returningResponse:&response error:&error];
482
483     if (error == nil) {
484         *finalURL = [response URL];
485         if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
486                 NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; 
487                 *responseHeaderDict = [httpResponse allHeaderFields];
488                 *statusCode = [httpResponse statusCode];
489         } else {
490             *responseHeaderDict = [NSDictionary dictionary];
491             *statusCode = 200;
492         }
493     } else {
494         *finalURL = URL;
495         *responseHeaderDict = [NSDictionary dictionary];
496         *statusCode = 404;
497     }
498
499     // notify the delegates
500     [self objectLoadedFromCacheWithURL:URL response:response size:[result length]];
501
502     return result;
503 }
504
505 - (BOOL)isReloading
506 {
507     return [[[self dataSource] request] cachePolicy] == NSURLRequestReloadIgnoringCacheData;
508 }
509
510 // We would like a better value for a maximum time_t,
511 // but there is no way to do that in C with any certainty.
512 // INT_MAX should work well enough for our purposes.
513 #define MAX_TIME_T ((time_t)INT_MAX)    
514
515 - (time_t)expiresTimeForResponse:(NSURLResponse *)response
516 {
517     // This check can be removed when the new Foundation method
518     // has been around long enough for everyone to have it.
519     if ([response respondsToSelector:@selector(_calculatedExpiration)]) {
520         NSTimeInterval expiration = [response _calculatedExpiration];
521         expiration += kCFAbsoluteTimeIntervalSince1970;
522         return expiration > MAX_TIME_T ? MAX_TIME_T : expiration;
523     }
524
525     // Fall back to the older calculation
526     time_t now = time(NULL);
527     NSTimeInterval lifetime = [response _freshnessLifetime];
528     if (lifetime < 0)
529         lifetime = 0;
530     
531     if (now + lifetime > MAX_TIME_T)
532         return MAX_TIME_T;
533     
534     return now + lifetime;
535 }
536
537 - (void)reportClientRedirectToURL:(NSURL *)URL delay:(NSTimeInterval)seconds fireDate:(NSDate *)date lockHistory:(BOOL)lockHistory isJavaScriptFormAction:(BOOL)isJavaScriptFormAction
538 {
539     [_frame _clientRedirectedTo:URL delay:seconds fireDate:date lockHistory:lockHistory isJavaScriptFormAction:(BOOL)isJavaScriptFormAction];
540 }
541
542 - (void)reportClientRedirectCancelled:(BOOL)cancelWithLoadInProgress
543 {
544     [_frame _clientRedirectCancelled:cancelWithLoadInProgress];
545 }
546
547 - (void)close
548 {
549     _frame = nil;
550 }
551
552 - (void)focusWindow
553 {
554     [[[_frame webView] _UIDelegateForwarder] webViewFocus:[_frame webView]];
555 }
556
557 - (void)unfocusWindow
558 {
559     if ([[self window] isKeyWindow] || [[[self window] attachedSheet] isKeyWindow]) {
560         [NSApp _cycleWindowsReversed:FALSE];
561     }
562 }
563
564 - (void)setIconURL:(NSURL *)URL
565 {
566     [[self dataSource] _setIconURL:URL];
567 }
568
569 - (void)setIconURL:(NSURL *)URL withType:(NSString *)type
570 {
571     [[self dataSource] _setIconURL:URL withType:type];
572 }
573
574 - (void)loadURL:(NSURL *)URL referrer:(NSString *)referrer reload:(BOOL)reload onLoadEvent:(BOOL)onLoad target:(NSString *)target triggeringEvent:(NSEvent *)event form:(DOMElement *)form formValues:(NSDictionary *)values
575 {
576     if ([target length] == 0) {
577         target = nil;
578     }
579
580     WebFrame *targetFrame = [_frame findFrameNamed:target];
581     WebFrameLoadType loadType;
582     
583     if (reload)
584         loadType = WebFrameLoadTypeReload;
585     else if (onLoad)
586         loadType = WebFrameLoadTypeOnLoadEvent;
587     else
588         loadType = WebFrameLoadTypeStandard;
589     [_frame _loadURL:URL referrer:referrer loadType:loadType target:target triggeringEvent:event form:form formValues:values];
590
591     if (targetFrame != nil && _frame != targetFrame) {
592         [[targetFrame _bridge] focusWindow];
593     }
594 }
595
596 - (void)postWithURL:(NSURL *)URL referrer:(NSString *)referrer target:(NSString *)target data:(NSData *)data contentType:(NSString *)contentType triggeringEvent:(NSEvent *)event form:(DOMElement *)form formValues:(NSDictionary *)values
597 {
598     if ([target length] == 0) {
599         target = nil;
600     }
601
602     WebFrame *targetFrame = [_frame findFrameNamed:target];
603
604     [_frame _postWithURL:URL referrer:(NSString *)referrer target:target data:data contentType:contentType triggeringEvent:event form:form formValues:values];
605
606     if (targetFrame != nil && _frame != targetFrame) {
607         [[targetFrame _bridge] focusWindow];
608     }
609 }
610
611 - (NSString *)generateFrameName
612 {
613     return [_frame _generateFrameName];
614 }
615
616 - (WebCoreBridge *)createChildFrameNamed:(NSString *)frameName withURL:(NSURL *)URL
617     renderPart:(KHTMLRenderPart *)childRenderPart
618     allowsScrolling:(BOOL)allowsScrolling marginWidth:(int)width marginHeight:(int)height
619 {
620     ASSERT(_frame != nil);
621     WebFrame *newFrame = [[_frame webView] _createFrameNamed:frameName inParent:_frame allowsScrolling:allowsScrolling];
622     if (newFrame == nil) {
623         return nil;
624     }
625     
626     [[newFrame _bridge] setRenderPart:childRenderPart];
627
628     [[newFrame frameView] _setMarginWidth:width];
629     [[newFrame frameView] _setMarginHeight:height];
630
631     [_frame _loadURL:URL intoChild:newFrame];
632
633     return [newFrame _bridge];
634 }
635
636 - (void)saveDocumentState: (NSArray *)documentState
637 {
638     WebHistoryItem *item = [_frame _itemForSavingDocState];
639     LOG(Loading, "%@: saving form state from to 0x%x", [_frame name], item);
640     if (item) {
641         [item setDocumentState: documentState];
642         // You might think we could save the scroll state here too, but unfortunately this
643         // often gets called after WebFrame::_transitionToCommitted has restored the scroll
644         // position of the next document.
645     }
646 }
647
648 - (NSArray *)documentState
649 {
650     LOG(Loading, "%@: restoring form state from item 0x%x", [_frame name], [_frame _itemForRestoringDocState]);
651     return [[_frame _itemForRestoringDocState] documentState];
652 }
653
654 - (BOOL)saveDocumentToPageCache: documentInfo
655 {
656     WebHistoryItem *item = [_frame _itemForSavingDocState];
657     if (![item hasPageCache]) {
658         return false;
659     }
660     [[item pageCache] setObject: documentInfo forKey: WebCorePageCacheStateKey];
661     return true;
662 }
663
664 - (NSString *)userAgentForURL:(NSURL *)URL
665 {
666     return [[_frame webView] userAgentForURL:URL];
667 }
668
669 - (BOOL)inNextKeyViewOutsideWebFrameViews
670 {
671     return _inNextKeyViewOutsideWebFrameViews;
672 }
673
674 - (NSView *)nextKeyViewOutsideWebFrameViews
675 {
676     _inNextKeyViewOutsideWebFrameViews = YES;
677     WebView *webView = [_frame webView];
678     // Do not ask webView for its next key view, but rather, ask it for 
679     // the next key view of the last view in its key view loop.
680     // Doing so gives us the correct answer as calculated by AppKit, 
681     // and makes HTML views behave like other views.
682     NSView *nextKeyView = [[webView _findLastViewInKeyViewLoop] nextKeyView];
683     _inNextKeyViewOutsideWebFrameViews = NO;
684     return nextKeyView;
685 }
686
687 - (NSView *)previousKeyViewOutsideWebFrameViews
688 {
689     WebView *webView = [_frame webView];
690     NSView *previousKeyView = [webView previousKeyView];
691     return previousKeyView;
692 }
693
694 - (BOOL)defersLoading
695 {
696     return [[_frame webView] defersCallbacks];
697 }
698
699 - (void)setDefersLoading:(BOOL)defers
700 {
701     [[_frame webView] setDefersCallbacks:defers];
702 }
703
704 - (void)setNeedsReapplyStyles
705 {
706     NSView <WebDocumentView> *view = [[_frame frameView] documentView];
707     if ([view isKindOfClass:[WebHTMLView class]]) {
708         [(WebHTMLView *)view setNeedsToApplyStyles:YES];
709         [view setNeedsLayout:YES];
710         [view setNeedsDisplay:YES];
711     }
712 }
713
714 // OK to be an NSString rather than an NSURL.
715 // This URL is only used for coloring visited links.
716 - (NSString *)requestedURLString
717 {
718     return [[[[self dataSource] request] URL] _web_originalDataAsString];
719 }
720
721 - (NSString *)incomingReferrer
722 {
723     return [[[self dataSource] request] HTTPReferrer];
724 }
725
726 - (NSView *)pluginViewWithPackage:(WebPluginPackage *)pluginPackage
727                        attributes:(NSDictionary *)attributes
728                           baseURL:(NSURL *)baseURL
729 {
730     WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
731
732     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
733     
734     [pluginPackage load];
735     
736     WebPluginController *pluginController = [docView _pluginController];
737     Class viewFactory = [pluginPackage viewFactory];
738     
739     if ([viewFactory respondsToSelector:@selector(plugInViewWithArguments:)]) {
740         NSDictionary *arguments = [NSDictionary dictionaryWithObjectsAndKeys:
741             baseURL, WebPlugInBaseURLKey,
742             attributes, WebPlugInAttributesKey,
743             pluginController, WebPlugInContainerKey,
744             nil];
745         LOG(Plugins, "arguments:\n%@", arguments);
746         return [viewFactory plugInViewWithArguments:arguments];
747     } else if ([viewFactory respondsToSelector:@selector(pluginViewWithArguments:)]) {
748         NSDictionary *arguments = [NSDictionary dictionaryWithObjectsAndKeys:
749             baseURL, WebPluginBaseURLKey,
750             attributes, WebPluginAttributesKey,
751             pluginController, WebPluginContainerKey,
752             nil];
753         LOG(Plugins, "arguments:\n%@", arguments);
754         return [viewFactory pluginViewWithArguments:arguments];
755     } else {
756         return nil;
757     }
758 }
759
760 - (NSView *)viewForPluginWithURL:(NSURL *)URL
761                       attributes:(NSArray *)attributesArray
762                          baseURL:(NSURL *)baseURL
763                         MIMEType:(NSString *)MIMEType;
764 {
765     NSRange r1, r2, r3;
766     uint i;
767
768     // Parse the attributesArray into key/value pairs.
769     // Store them in a dictionary so they can be passed to WebPlugins.
770     // Store them in ordered arrays so they can be passed to Netscape plug-ins.
771     NSMutableDictionary *attributes = [[NSMutableDictionary alloc] init];
772     NSMutableArray *attributeKeys = [[NSMutableArray alloc] init];
773     NSMutableArray *attributeValues = [[NSMutableArray alloc] init];
774     for (i = 0; i < [attributesArray count]; i++) {
775         NSString *attribute = [attributesArray objectAtIndex:i];
776         if ([attribute rangeOfString:@"__KHTML__"].length == 0) {
777             r1 = [attribute rangeOfString:@"="];
778             r2 = [attribute rangeOfString:@"\""];
779             r3.location = r2.location + 1;
780             r3.length = [attribute length] - r2.location - 2; // don't include quotes
781             NSString *key = [attribute substringToIndex:r1.location];
782             NSString *value = [attribute substringWithRange:r3];
783             [attributes setObject:value forKey:key];
784             [attributeKeys addObject:key];
785             [attributeValues addObject:value];
786         }
787     }
788
789     WebBasePluginPackage *pluginPackage = nil;
790     NSView *view = nil;
791     int errorCode = 0;
792     
793     if ([MIMEType length] != 0) {
794         pluginPackage = [[WebPluginDatabase installedPlugins] pluginForMIMEType:MIMEType];
795     } else {
796         MIMEType = nil;
797     }
798     
799     NSString *extension = [[URL path] pathExtension];
800     if (!pluginPackage && [extension length] != 0) {
801         pluginPackage = [[WebPluginDatabase installedPlugins] pluginForExtension:extension];
802         if (pluginPackage) {
803             NSString *newMIMEType = [pluginPackage MIMETypeForExtension:extension];
804             if ([newMIMEType length] != 0) {
805                 MIMEType = newMIMEType;
806             }
807         }
808     }
809
810     if (pluginPackage) {
811         if ([pluginPackage isKindOfClass:[WebPluginPackage class]]) {
812             view = [self pluginViewWithPackage:(WebPluginPackage *)pluginPackage
813                                     attributes:attributes
814                                        baseURL:baseURL];
815         } else if ([pluginPackage isKindOfClass:[WebNetscapePluginPackage class]]) {
816             view = [[[WebNetscapePluginEmbeddedView alloc] initWithFrame:NSZeroRect
817                                                                   plugin:(WebNetscapePluginPackage *)pluginPackage
818                                                                      URL:URL
819                                                                  baseURL:baseURL
820                                                                 MIMEType:MIMEType
821                                                            attributeKeys:attributeKeys
822                                                          attributeValues:attributeValues] autorelease];
823         } else {
824             ASSERT_NOT_REACHED();
825         }
826     } else {
827         errorCode = WebKitErrorCannotFindPlugIn;
828     }
829
830     if (!errorCode && !view) {
831         errorCode = WebKitErrorCannotLoadPlugIn;
832     }
833
834     if (errorCode) {
835         NSError *error = [[NSError alloc] _initWithPluginErrorCode:errorCode
836                                                         contentURL:URL
837                                                      pluginPageURL:[NSURL _web_URLWithUserTypedString:[attributes objectForKey:@"pluginspage"]]
838                                                         pluginName:[pluginPackage name]
839                                                           MIMEType:MIMEType];
840         view = [[[WebNullPluginView alloc] initWithFrame:NSZeroRect error:error] autorelease];
841         [error release];
842     }
843
844     ASSERT(view);
845
846     [attributes release];
847     [attributeKeys release];
848     [attributeValues release];
849     
850     return view;
851 }
852
853 - (NSView *)viewForJavaAppletWithFrame:(NSRect)theFrame
854                             attributes:(NSDictionary *)attributes
855                                baseURL:(NSURL *)baseURL;
856 {
857     NSString *MIMEType = @"application/x-java-applet";
858     WebBasePluginPackage *pluginPackage;
859     NSView *view = nil;
860     
861     pluginPackage = [[WebPluginDatabase installedPlugins] pluginForMIMEType:MIMEType];
862
863     if (pluginPackage) {
864         if ([pluginPackage isKindOfClass:[WebPluginPackage class]]) {
865             NSMutableDictionary *theAttributes = [NSMutableDictionary dictionary];
866             [theAttributes addEntriesFromDictionary:attributes];
867             [theAttributes setObject:[NSString stringWithFormat:@"%d", (int)theFrame.size.width] forKey:@"width"];
868             [theAttributes setObject:[NSString stringWithFormat:@"%d", (int)theFrame.size.height] forKey:@"height"];
869             
870             view = [self pluginViewWithPackage:(WebPluginPackage *)pluginPackage
871                                     attributes:theAttributes
872                                        baseURL:baseURL];
873         } else if ([pluginPackage isKindOfClass:[WebNetscapePluginPackage class]]) {
874             // Convert the attributes dictionary to 2 string arrays because this is what Netscape plug-ins expect.
875             NSMutableArray *attributeKeys = [[NSMutableArray alloc] init];
876             NSMutableArray *attributeValues = [[NSMutableArray alloc] init];
877             NSEnumerator *enumerator = [attributes keyEnumerator];
878             NSString *key;
879             
880             while ((key = [enumerator nextObject]) != nil) {
881                 [attributeKeys addObject:key];
882                 [attributeValues addObject:[attributes objectForKey:key]];
883             }
884             view = [[[WebNetscapePluginEmbeddedView alloc] initWithFrame:theFrame
885                                                                   plugin:(WebNetscapePluginPackage *)pluginPackage
886                                                                      URL:nil
887                                                                  baseURL:baseURL
888                                                                 MIMEType:MIMEType
889                                                            attributeKeys:attributeKeys
890                                                          attributeValues:attributeValues] autorelease];
891             [attributeKeys release];
892             [attributeValues release];
893         } else {
894             ASSERT_NOT_REACHED();
895         }
896     }
897
898     if (!view) {
899         NSError *error = [[NSError alloc] _initWithPluginErrorCode:WebKitErrorJavaUnavailable
900                                                         contentURL:nil
901                                                      pluginPageURL:nil
902                                                         pluginName:[pluginPackage name]
903                                                           MIMEType:MIMEType];
904         view = [[[WebNullPluginView alloc] initWithFrame:theFrame error:error] autorelease];
905         [error release];
906     }
907
908     ASSERT(view);
909
910     return view;
911 }
912
913 #ifndef NDEBUG
914 static BOOL loggedObjectCacheSize = NO;
915 #endif
916
917
918 -(int)getObjectCacheSize
919 {
920     vm_size_t memSize = WebSystemMainMemory();
921     int cacheSize = [[WebPreferences standardPreferences] _objectCacheSize];
922     int multiplier = 1;
923     if (memSize > 1024 * 1024 * 1024)
924         multiplier = 4;
925     else if (memSize > 512 * 1024 * 1024)
926         multiplier = 2;
927
928 #ifndef NDEBUG
929     if (!loggedObjectCacheSize){
930         LOG (CacheSizes, "Object cache size set to %d bytes.", cacheSize * multiplier);
931         loggedObjectCacheSize = YES;
932     }
933 #endif
934
935     return cacheSize * multiplier;
936 }
937
938 - (BOOL)frameRequiredForMIMEType:(NSString *)MIMEType URL:(NSURL *)URL
939 {
940     if ([MIMEType length] == 0) {
941         NSString *extension = [[URL path] pathExtension];
942         if ([extension length] > 0 && [[WebPluginDatabase installedPlugins] pluginForExtension:extension] != nil) {
943             // If no MIME type is specified, use a plug-in if we have one that can handle the extension.
944             return NO;
945         } else {
946             // Else, create a frame and attempt to load the URL in there.
947             return YES;
948         }
949     }
950     
951     Class viewClass = [WebFrameView _viewClassForMIMEType:MIMEType];
952     if (!viewClass) {
953         // Want to display a "plugin not found" dialog/image, so let a plugin get made.
954         return NO;
955     }
956         
957     // If we're a supported type other than a plugin, we want to make a frame.
958     // Ultimately we should just use frames for all mime types (plugins and HTML/XML/text documents),
959     // but for now we're burdened with making a distinction between the two.
960     return !([viewClass isSubclassOfClass:[WebNetscapePluginDocumentView class]] ||
961              [viewClass conformsToProtocol:@protocol(WebPlugin)]);
962 }
963
964 - (void)loadEmptyDocumentSynchronously
965 {
966     NSURL *url = [[NSURL alloc] initWithString:@""];
967     NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
968     [_frame loadRequest:request];
969     [request release];
970     [url release];
971 }
972
973 - (NSString *)MIMETypeForPath:(NSString *)path
974 {
975     ASSERT(path);
976     NSString *extension = [path pathExtension];
977     NSString *type = [[NSURLFileTypeMappings sharedMappings] MIMETypeForExtension:extension];
978     return [type length] == 0 ? @"application/octet-stream" : type;
979 }
980
981 - (void)handleMouseDragged:(NSEvent *)event
982 {
983     WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
984
985     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
986
987     [docView _handleMouseDragged:event];
988 }
989
990 - (void)handleAutoscrollForMouseDragged:(NSEvent *)event;
991 {
992     WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
993
994     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
995
996     [docView _handleAutoscrollForMouseDragged:event];
997 }
998
999 - (BOOL)mayStartDragWithMouseDragged:(NSEvent *)event
1000 {
1001     WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
1002
1003     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
1004
1005     return [docView _mayStartDragWithMouseDragged:event];
1006 }
1007
1008 - (int)historyLength
1009 {
1010     return [[[_frame webView] backForwardList] backListCount] + 1;
1011 }
1012
1013 - (void)goBackOrForward:(int)distance
1014 {
1015     if (distance == 0) {
1016         return;
1017     }
1018     WebView *webView = [_frame webView];
1019     WebBackForwardList *list = [webView backForwardList];
1020     WebHistoryItem *item = [list itemAtIndex:distance];
1021     if (!item) {
1022         if (distance > 0) {
1023             int forwardListCount = [list forwardListCount];
1024             if (forwardListCount > 0) {
1025                 item = [list itemAtIndex:forwardListCount];
1026             }
1027         } else {
1028             int backListCount = [list forwardListCount];
1029             if (backListCount > 0) {
1030                 item = [list itemAtIndex:-backListCount];
1031             }
1032         }
1033     }
1034     if (item) {
1035         [webView goToBackForwardItem:item];
1036     }
1037 }
1038
1039 static id <WebFormDelegate> formDelegate(WebBridge *self)
1040 {
1041     ASSERT(self->_frame != nil);
1042     return [[self->_frame webView] _formDelegate];
1043 }
1044
1045 #define FormDelegateLog(ctrl)  LOG(FormDelegate, "control=%@", ctrl)
1046
1047 - (void)controlTextDidBeginEditing:(NSNotification *)obj
1048 {
1049     FormDelegateLog([obj object]);
1050     [formDelegate(self) controlTextDidBeginEditing:obj inFrame:_frame];
1051 }
1052
1053 - (void)controlTextDidEndEditing:(NSNotification *)obj
1054 {
1055     FormDelegateLog([obj object]);
1056     [formDelegate(self) controlTextDidEndEditing:obj inFrame:_frame];
1057 }
1058
1059 - (void)controlTextDidChange:(NSNotification *)obj
1060 {
1061     FormDelegateLog([obj object]);
1062     [formDelegate(self) controlTextDidChange:obj inFrame:_frame];
1063 }
1064
1065 - (BOOL)control:(NSControl *)control textShouldBeginEditing:(NSText *)fieldEditor
1066 {
1067     FormDelegateLog(control);
1068     return [formDelegate(self) control:control textShouldBeginEditing:fieldEditor inFrame:_frame];
1069 }
1070
1071 - (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor
1072 {
1073     FormDelegateLog(control);
1074     return [formDelegate(self) control:control textShouldEndEditing:fieldEditor inFrame:_frame];
1075 }
1076
1077 - (BOOL)control:(NSControl *)control didFailToFormatString:(NSString *)string errorDescription:(NSString *)error
1078 {
1079     FormDelegateLog(control);
1080     return [formDelegate(self) control:control didFailToFormatString:string errorDescription:error inFrame:_frame];
1081 }
1082
1083 - (void)control:(NSControl *)control didFailToValidatePartialString:(NSString *)string errorDescription:(NSString *)error
1084 {
1085     FormDelegateLog(control);
1086     [formDelegate(self) control:control didFailToValidatePartialString:string errorDescription:error inFrame:_frame];
1087 }
1088
1089 - (BOOL)control:(NSControl *)control isValidObject:(id)obj
1090 {
1091     FormDelegateLog(control);
1092     return [formDelegate(self) control:control isValidObject:obj inFrame:_frame];
1093 }
1094
1095 - (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector
1096 {
1097     FormDelegateLog(control);
1098     return [formDelegate(self) control:control textView:textView doCommandBySelector:commandSelector inFrame:_frame];
1099 }
1100
1101 - (void)frameDetached
1102 {
1103     // Put _frame into a local variable because _detachFromParent
1104     // will disconnect the bridge from the frame and make _frame nil.
1105     WebFrame *frame = _frame;
1106
1107     [frame stopLoading];
1108     [frame _detachFromParent];
1109     [[frame parentFrame] _removeChild:frame];
1110 }
1111
1112 - (void)setHasBorder:(BOOL)hasBorder
1113 {
1114     [[_frame frameView] _setHasBorder:hasBorder];
1115 }
1116
1117 - (void)_retrieveKeyboardUIModeFromPreferences:(NSNotification *)notification
1118 {
1119     CFPreferencesAppSynchronize(UniversalAccessDomain);
1120
1121     BOOL keyExistsAndHasValidFormat;
1122     int mode = CFPreferencesGetAppIntegerValue(AppleKeyboardUIMode, UniversalAccessDomain, &keyExistsAndHasValidFormat);
1123     
1124     // The keyboard access mode is reported by two bits:
1125     // Bit 0 is set if feature is on
1126     // Bit 1 is set if full keyboard access works for any control, not just text boxes and lists
1127     // We require both bits to be on.
1128     // I do not know that we would ever get one bit on and the other off since
1129     // checking the checkbox in system preferences which is marked as "Turn on full keyboard access"
1130     // turns on both bits.
1131     _keyboardUIMode = (mode & 0x2) ? WebCoreKeyboardAccessFull : WebCoreKeyboardAccessDefault;
1132     
1133     // check for tabbing to links; also, we always do full keyboard access when this preference is set,
1134     // regardless of the system preferences setting
1135     if ([[WebPreferences standardPreferences] tabsToLinks]) {
1136         _keyboardUIMode |= WebCoreKeyboardAccessTabsToLinks;
1137         _keyboardUIMode |= WebCoreKeyboardAccessFull;
1138     }
1139 }
1140
1141 - (WebCoreKeyboardUIMode)keyboardUIMode
1142 {
1143     if (!_keyboardUIModeAccessed) {
1144         _keyboardUIModeAccessed = YES;
1145         [self _retrieveKeyboardUIModeFromPreferences:nil];
1146         
1147         [[NSDistributedNotificationCenter defaultCenter] 
1148             addObserver:self selector:@selector(_retrieveKeyboardUIModeFromPreferences:) 
1149             name:KeyboardUIModeDidChangeNotification object:nil];
1150
1151         [[NSNotificationCenter defaultCenter] 
1152             addObserver:self selector:@selector(_retrieveKeyboardUIModeFromPreferences:) 
1153                    name:WebPreferencesChangedNotification object:nil];
1154     }
1155     return _keyboardUIMode;
1156 }
1157
1158 - (void)didSetName:(NSString *)name
1159 {
1160     [_frame _setName:name];
1161 }
1162
1163 - (NSFileWrapper *)fileWrapperForURL:(NSURL *)URL
1164 {
1165     return [[_frame dataSource] _fileWrapperForURL:URL];
1166 }
1167
1168 - (void)print
1169 {
1170     id wd = [[_frame webView] UIDelegate];
1171     
1172     if ([wd respondsToSelector:@selector(webViewPrint:)]) {
1173         [wd webViewPrint:[_frame webView]];
1174     } else {
1175         [[WebDefaultUIDelegate sharedUIDelegate] webViewPrint:[_frame webView]];
1176     }
1177 }
1178
1179 // NOTE: pollForAppletInView: will block until the block is ready to use, or
1180 // until a timeout is exceeded.  It will return nil if the timeour is
1181 // exceeded.
1182 - (jobject)pollForAppletInView: (NSView *)view
1183 {
1184     jobject applet = 0;
1185     
1186     if ([view respondsToSelector: @selector(pollForAppletInWindow:)]) {
1187         // The Java VM needs the containing window of the view to
1188         // initialize.  The view may not yet be in the window's view 
1189         // hierarchy, so we have to pass the window when requesting
1190         // the applet.
1191         applet = [view pollForAppletInWindow:[[_frame webView] window]];
1192     }
1193     
1194     return applet;
1195 }
1196
1197 - (void)postDidChangeNotification
1198 {
1199     [[_frame webView] _updateFontPanel];
1200     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewDidChangeNotification object:[_frame webView]];
1201 }
1202
1203 - (void)postDidChangeSelectionNotification
1204 {
1205     [[_frame webView] _updateFontPanel];
1206     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewDidChangeSelectionNotification object:[_frame webView]];
1207 }
1208
1209 - (void)registerCommandForUndo:(id)arg
1210 {
1211     NSUndoManager *undoManager = [[_frame webView] undoManager];
1212     [undoManager registerUndoWithTarget:self selector:@selector(undoEditing:) object:arg];
1213     _haveUndoRedoOperations = YES;
1214 }
1215
1216 - (void)registerCommandForRedo:(id)arg
1217 {
1218     NSUndoManager *undoManager = [[_frame webView] undoManager];
1219     [undoManager registerUndoWithTarget:self selector:@selector(redoEditing:) object:arg];
1220     _haveUndoRedoOperations = YES;
1221 }
1222
1223 - (void)clearUndoRedoOperations
1224 {
1225     if (_haveUndoRedoOperations) {
1226         NSUndoManager *undoManager = [[_frame webView] undoManager];
1227         [undoManager removeAllActionsWithTarget:self];
1228         _haveUndoRedoOperations = NO;
1229     }
1230 }
1231
1232 - (void)editingKeyDown:(NSEvent *)event
1233 {
1234     [[_frame webView] _editingKeyDown:event];
1235 }
1236
1237 - (void)issueUndoCommand
1238 {
1239     NSUndoManager *undoManager = [[_frame webView] undoManager];
1240     if ([undoManager canUndo])
1241         [undoManager undo];
1242 }
1243
1244 - (void)issueRedoCommand
1245 {
1246     NSUndoManager *undoManager = [[_frame webView] undoManager];
1247     if ([undoManager canRedo])
1248         [undoManager redo];
1249 }
1250
1251 - (void)issueCutCommand
1252 {
1253     [[_frame webView] cut:nil];
1254 }
1255
1256 - (void)issueCopyCommand
1257 {
1258     [[_frame webView] copy:nil];
1259 }
1260
1261 - (void)issuePasteCommand
1262 {
1263     [[_frame webView] paste:nil];
1264 }
1265
1266 - (void)setIsSelected:(BOOL)isSelected forView:(NSView *)view
1267 {
1268     if ([view respondsToSelector:@selector(webPlugInSetIsSelected)]) {
1269         [view webPlugInSetIsSelected:isSelected];
1270     }
1271     else if ([view respondsToSelector:@selector(setIsSelected)]) {
1272         [view setIsSelected:isSelected];
1273     }
1274 }
1275
1276 - (NSString *)overrideMediaType
1277 {
1278     return [[_frame webView] mediaStyle];
1279 }
1280
1281 @end