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