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