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