f11c9db4970954620b07658ba337a89d815086c7
[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/WebPluginViewFactory.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             nil];
817         LOG(Plugins, "arguments:\n%@", arguments);
818     } else if ([viewFactory respondsToSelector:@selector(pluginViewWithArguments:)]) {
819         arguments = [NSDictionary dictionaryWithObjectsAndKeys:
820             baseURL, WebPluginBaseURLKey,
821             attributes, WebPluginAttributesKey,
822             pluginController, WebPluginContainerKey,
823             nil];
824         LOG(Plugins, "arguments:\n%@", arguments);
825     }
826     
827     view = [WebPluginController plugInViewWithArguments:arguments fromPluginPackage:pluginPackage];
828     
829     [attributes release];
830     return view;
831 }
832
833 - (NSString *)valueForKey:(NSString *)key keys:(NSArray *)keys values:(NSArray *)values
834 {
835     unsigned count = [keys count];
836     unsigned i;
837     for (i = 0; i < count; i++) {
838         if ([[keys objectAtIndex:i] _web_isCaseInsensitiveEqualToString:key]) {
839             return [values objectAtIndex:i];
840         }
841     }
842     return nil;
843 }
844
845 - (NSView *)viewForPluginWithURL:(NSURL *)URL
846                   attributeNames:(NSArray *)attributeNames
847                  attributeValues:(NSArray *)attributeValues
848                         MIMEType:(NSString *)MIMEType
849 {
850     ASSERT([attributeNames count] == [attributeValues count]);
851
852     WebBasePluginPackage *pluginPackage = nil;
853     NSView *view = nil;
854     int errorCode = 0;
855     
856     if ([MIMEType length] != 0) {
857         pluginPackage = [[WebPluginDatabase installedPlugins] pluginForMIMEType:MIMEType];
858     } else {
859         MIMEType = nil;
860     }
861     
862     NSString *extension = [[URL path] pathExtension];
863     if (!pluginPackage && [extension length] != 0) {
864         pluginPackage = [[WebPluginDatabase installedPlugins] pluginForExtension:extension];
865         if (pluginPackage) {
866             NSString *newMIMEType = [pluginPackage MIMETypeForExtension:extension];
867             if ([newMIMEType length] != 0) {
868                 MIMEType = newMIMEType;
869             }
870         }
871     }
872
873     NSURL *baseURL = [[[_frame dataSource] response] URL];
874     if (pluginPackage) {
875         if ([pluginPackage isKindOfClass:[WebPluginPackage class]]) {
876             view = [self pluginViewWithPackage:(WebPluginPackage *)pluginPackage
877                                 attributeNames:attributeNames
878                                attributeValues:attributeValues
879                                        baseURL:baseURL];
880         } else if ([pluginPackage isKindOfClass:[WebNetscapePluginPackage class]]) {
881             view = [[[WebNetscapePluginEmbeddedView alloc] initWithFrame:NSZeroRect
882                                                                   plugin:(WebNetscapePluginPackage *)pluginPackage
883                                                                      URL:URL
884                                                                  baseURL:baseURL
885                                                                 MIMEType:MIMEType
886                                                            attributeKeys:attributeNames
887                                                          attributeValues:attributeValues] autorelease];
888         } else {
889             ASSERT_NOT_REACHED();
890         }
891     } else {
892         errorCode = WebKitErrorCannotFindPlugIn;
893     }
894
895     if (!errorCode && !view) {
896         errorCode = WebKitErrorCannotLoadPlugIn;
897     }
898
899     if (errorCode) {
900         NSString *pluginPage = [self valueForKey:@"pluginspage" keys:attributeNames values:attributeValues];
901         NSURL *pluginPageURL = pluginPage != nil ? [self URLWithAttributeString:pluginPage] : nil;
902         NSError *error = [[NSError alloc] _initWithPluginErrorCode:errorCode
903                                                         contentURL:URL
904                                                      pluginPageURL:pluginPageURL
905                                                         pluginName:[pluginPackage name]
906                                                           MIMEType:MIMEType];
907         view = [[[WebNullPluginView alloc] initWithFrame:NSZeroRect error:error] autorelease];
908         [error release];
909     }
910     
911     ASSERT(view);
912     return view;
913 }
914
915 - (NSView *)viewForJavaAppletWithFrame:(NSRect)theFrame
916                         attributeNames:(NSArray *)attributeNames
917                        attributeValues:(NSArray *)attributeValues
918                                baseURL:(NSURL *)baseURL;
919 {
920     NSString *MIMEType = @"application/x-java-applet";
921     WebBasePluginPackage *pluginPackage;
922     NSView *view = nil;
923     
924     pluginPackage = [[WebPluginDatabase installedPlugins] pluginForMIMEType:MIMEType];
925
926     if (pluginPackage) {
927         if ([pluginPackage isKindOfClass:[WebPluginPackage class]]) {
928             // For some reason, the Java plug-in requires that we pass the dimension of the plug-in as attributes.
929             NSMutableArray *names = [attributeNames mutableCopy];
930             NSMutableArray *values = [attributeValues mutableCopy];
931             if ([self valueForKey:@"width" keys:attributeNames values:attributeValues] == nil) {
932                 [names addObject:@"width"];
933                 [values addObject:[NSString stringWithFormat:@"%d", (int)theFrame.size.width]];
934             }
935             if ([self valueForKey:@"height" keys:attributeNames values:attributeValues] == nil) {
936                 [names addObject:@"height"];
937                 [values addObject:[NSString stringWithFormat:@"%d", (int)theFrame.size.height]];
938             }
939             view = [self pluginViewWithPackage:(WebPluginPackage *)pluginPackage
940                                 attributeNames:names
941                                attributeValues:values
942                                        baseURL:baseURL];
943             [names release];
944             [values release];
945         } else if ([pluginPackage isKindOfClass:[WebNetscapePluginPackage class]]) {
946             view = [[[WebNetscapePluginEmbeddedView alloc] initWithFrame:theFrame
947                                                                   plugin:(WebNetscapePluginPackage *)pluginPackage
948                                                                      URL:nil
949                                                                  baseURL:baseURL
950                                                                 MIMEType:MIMEType
951                                                            attributeKeys:attributeNames
952                                                          attributeValues:attributeValues] autorelease];
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 isSubclassOfClass:[WebPluginDocumentView class]]);
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 - (BOOL)canGoBackOrForward:(int)distance
1081 {
1082     if (distance == 0)
1083         return TRUE;
1084
1085     if (distance > 0 && distance <= [[[_frame webView] backForwardList] forwardListCount])
1086         return TRUE;
1087
1088     if (distance < 0 && -distance <= [[[_frame webView] backForwardList] backListCount])
1089         return TRUE;
1090     
1091     return FALSE;
1092 }
1093
1094 - (void)goBackOrForward:(int)distance
1095 {
1096     if (distance == 0) {
1097         return;
1098     }
1099     WebView *webView = [_frame webView];
1100     WebBackForwardList *list = [webView backForwardList];
1101     WebHistoryItem *item = [list itemAtIndex:distance];
1102     if (!item) {
1103         if (distance > 0) {
1104             int forwardListCount = [list forwardListCount];
1105             if (forwardListCount > 0) {
1106                 item = [list itemAtIndex:forwardListCount];
1107             }
1108         } else {
1109             int backListCount = [list forwardListCount];
1110             if (backListCount > 0) {
1111                 item = [list itemAtIndex:-backListCount];
1112             }
1113         }
1114     }
1115     if (item) {
1116         [webView goToBackForwardItem:item];
1117     }
1118 }
1119
1120 static id <WebFormDelegate> formDelegate(WebBridge *self)
1121 {
1122     ASSERT(self->_frame != nil);
1123     return [[self->_frame webView] _formDelegate];
1124 }
1125
1126 #define FormDelegateLog(ctrl)  LOG(FormDelegate, "control=%@", ctrl)
1127
1128 - (void)controlTextDidBeginEditing:(NSNotification *)obj
1129 {
1130     FormDelegateLog([obj object]);
1131     [formDelegate(self) controlTextDidBeginEditing:obj inFrame:_frame];
1132 }
1133
1134 - (void)controlTextDidEndEditing:(NSNotification *)obj
1135 {
1136     FormDelegateLog([obj object]);
1137     [formDelegate(self) controlTextDidEndEditing:obj inFrame:_frame];
1138 }
1139
1140 - (void)controlTextDidChange:(NSNotification *)obj
1141 {
1142     FormDelegateLog([obj object]);
1143     [formDelegate(self) controlTextDidChange:obj inFrame:_frame];
1144 }
1145
1146 - (BOOL)control:(NSControl *)control textShouldBeginEditing:(NSText *)fieldEditor
1147 {
1148     FormDelegateLog(control);
1149     return [formDelegate(self) control:control textShouldBeginEditing:fieldEditor inFrame:_frame];
1150 }
1151
1152 - (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor
1153 {
1154     FormDelegateLog(control);
1155     return [formDelegate(self) control:control textShouldEndEditing:fieldEditor inFrame:_frame];
1156 }
1157
1158 - (BOOL)control:(NSControl *)control didFailToFormatString:(NSString *)string errorDescription:(NSString *)error
1159 {
1160     FormDelegateLog(control);
1161     return [formDelegate(self) control:control didFailToFormatString:string errorDescription:error inFrame:_frame];
1162 }
1163
1164 - (void)control:(NSControl *)control didFailToValidatePartialString:(NSString *)string errorDescription:(NSString *)error
1165 {
1166     FormDelegateLog(control);
1167     [formDelegate(self) control:control didFailToValidatePartialString:string errorDescription:error inFrame:_frame];
1168 }
1169
1170 - (BOOL)control:(NSControl *)control isValidObject:(id)obj
1171 {
1172     FormDelegateLog(control);
1173     return [formDelegate(self) control:control isValidObject:obj inFrame:_frame];
1174 }
1175
1176 - (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector
1177 {
1178     FormDelegateLog(control);
1179     return [formDelegate(self) control:control textView:textView doCommandBySelector:commandSelector inFrame:_frame];
1180 }
1181
1182 - (void)frameDetached
1183 {
1184     // Put _frame into a local variable because _detachFromParent
1185     // will disconnect the bridge from the frame and make _frame nil.
1186     WebFrame *frame = _frame;
1187
1188     [frame stopLoading];
1189     [frame _detachFromParent];
1190     [[frame parentFrame] _removeChild:frame];
1191 }
1192
1193 - (void)setHasBorder:(BOOL)hasBorder
1194 {
1195     [[_frame frameView] _setHasBorder:hasBorder];
1196 }
1197
1198 - (void)_retrieveKeyboardUIModeFromPreferences:(NSNotification *)notification
1199 {
1200     CFPreferencesAppSynchronize(UniversalAccessDomain);
1201
1202     BOOL keyExistsAndHasValidFormat;
1203     int mode = CFPreferencesGetAppIntegerValue(AppleKeyboardUIMode, UniversalAccessDomain, &keyExistsAndHasValidFormat);
1204     
1205     // The keyboard access mode is reported by two bits:
1206     // Bit 0 is set if feature is on
1207     // Bit 1 is set if full keyboard access works for any control, not just text boxes and lists
1208     // We require both bits to be on.
1209     // I do not know that we would ever get one bit on and the other off since
1210     // checking the checkbox in system preferences which is marked as "Turn on full keyboard access"
1211     // turns on both bits.
1212     _keyboardUIMode = (mode & 0x2) ? WebCoreKeyboardAccessFull : WebCoreKeyboardAccessDefault;
1213     
1214     // check for tabbing to links
1215     if ([[WebPreferences standardPreferences] tabsToLinks]) {
1216         _keyboardUIMode |= WebCoreKeyboardAccessTabsToLinks;
1217     }
1218 }
1219
1220 - (WebCoreKeyboardUIMode)keyboardUIMode
1221 {
1222     if (!_keyboardUIModeAccessed) {
1223         _keyboardUIModeAccessed = YES;
1224         [self _retrieveKeyboardUIModeFromPreferences:nil];
1225         
1226         [[NSDistributedNotificationCenter defaultCenter] 
1227             addObserver:self selector:@selector(_retrieveKeyboardUIModeFromPreferences:) 
1228             name:KeyboardUIModeDidChangeNotification object:nil];
1229
1230         [[NSNotificationCenter defaultCenter] 
1231             addObserver:self selector:@selector(_retrieveKeyboardUIModeFromPreferences:) 
1232                    name:WebPreferencesChangedNotification object:nil];
1233     }
1234     return _keyboardUIMode;
1235 }
1236
1237 - (void)didSetName:(NSString *)name
1238 {
1239     [_frame _setName:name];
1240 }
1241
1242 - (NSFileWrapper *)fileWrapperForURL:(NSURL *)URL
1243 {
1244     return [[_frame dataSource] _fileWrapperForURL:URL];
1245 }
1246
1247 - (void)print
1248 {
1249     id wd = [[_frame webView] UIDelegate];
1250     
1251     if ([wd respondsToSelector:@selector(webView:printFrameView:)]) {
1252         [wd webView:[_frame webView] printFrameView:[_frame frameView]];
1253     } else if ([wd respondsToSelector:@selector(webViewPrint:)]) {
1254         // Backward-compatible, but webViewPrint: was never public, so probably not needed.
1255         [wd webViewPrint:[_frame webView]];
1256     } else {
1257         [[WebDefaultUIDelegate sharedUIDelegate] webView:[_frame webView] printFrameView:[_frame frameView]];
1258     }
1259 }
1260
1261 - (jobject)getAppletInView:(NSView *)view
1262 {
1263     jobject applet = 0;
1264
1265     if ([view respondsToSelector: @selector(webPlugInGetApplet)])
1266         applet = [view webPlugInGetApplet];
1267     else
1268         applet = [self pollForAppletInView:view];
1269         
1270     return applet;
1271 }
1272
1273 // NOTE: pollForAppletInView: will block until the block is ready to use, or
1274 // until a timeout is exceeded.  It will return nil if the timeour is
1275 // exceeded.
1276 // Deprecated, use getAppletInView:.
1277 - (jobject)pollForAppletInView: (NSView *)view
1278 {
1279     jobject applet = 0;
1280     
1281     if ([view respondsToSelector: @selector(pollForAppletInWindow:)]) {
1282         // The Java VM needs the containing window of the view to
1283         // initialize.  The view may not yet be in the window's view 
1284         // hierarchy, so we have to pass the window when requesting
1285         // the applet.
1286         applet = [view pollForAppletInWindow:[[_frame webView] window]];
1287     }
1288     
1289     return applet;
1290 }
1291
1292 - (void)respondToChangedContents
1293 {
1294     NSView <WebDocumentView> *view = [[_frame frameView] documentView];
1295     if ([view isKindOfClass:[WebHTMLView class]]) {
1296         [(WebHTMLView *)view _updateFontPanel];
1297     }
1298     [[_frame webView] setTypingStyle:nil];
1299     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewDidChangeNotification object:[_frame webView]];
1300 }
1301
1302 - (void)respondToChangedSelection
1303 {
1304     NSView <WebDocumentView> *view = [[_frame frameView] documentView];
1305     if ([view isKindOfClass:[WebHTMLView class]]) {
1306         [(WebHTMLView *)view _selectionChanged];
1307     }
1308     [[_frame webView] setTypingStyle:nil];
1309     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewDidChangeSelectionNotification object:[_frame webView]];
1310 }
1311
1312 - (NSUndoManager *)undoManager
1313 {
1314     return [[_frame webView] undoManager];
1315 }
1316
1317 - (void)issueCutCommand
1318 {
1319     [[_frame webView] cut:nil];
1320 }
1321
1322 - (void)issueCopyCommand
1323 {
1324     [[_frame webView] copy:nil];
1325 }
1326
1327 - (void)issuePasteCommand
1328 {
1329     [[_frame webView] paste:nil];
1330 }
1331
1332 - (void)setIsSelected:(BOOL)isSelected forView:(NSView *)view
1333 {
1334     if ([view respondsToSelector:@selector(webPlugInSetIsSelected:)]) {
1335         [view webPlugInSetIsSelected:isSelected];
1336     }
1337     else if ([view respondsToSelector:@selector(setIsSelected:)]) {
1338         [view setIsSelected:isSelected];
1339     }
1340 }
1341
1342 - (NSString *)overrideMediaType
1343 {
1344     return [[_frame webView] mediaStyle];
1345 }
1346
1347 - (BOOL)isEditable
1348 {
1349     return [[_frame webView] isEditable];
1350 }
1351
1352 - (BOOL)shouldBeginEditing:(DOMRange *)range
1353 {
1354     return [[_frame webView] _shouldBeginEditingInDOMRange:range];
1355 }
1356
1357 - (BOOL)shouldEndEditing:(DOMRange *)range
1358 {
1359     return [[_frame webView] _shouldEndEditingInDOMRange:range];
1360 }
1361
1362 - (void)windowObjectCleared
1363 {
1364     WebView *wv = [_frame webView];
1365     [[wv _frameLoadDelegateForwarder] webView:wv windowScriptObjectAvailable:[self windowScriptObject]];
1366 }
1367
1368 - (int)spellCheckerDocumentTag
1369 {
1370     return [[_frame webView] spellCheckerDocumentTag];
1371 }
1372
1373 - (BOOL)isContinuousSpellCheckingEnabled
1374 {
1375     return [[_frame webView] isContinuousSpellCheckingEnabled];
1376 }
1377
1378 - (void)didFirstLayout
1379 {
1380     WebView *wv = [_frame webView];
1381     [[wv _frameLoadDelegateForwarder] webView:wv didFirstLayoutInFrame:_frame];
1382 }
1383
1384 - (void)dashboardRegionsChanged:(NSMutableDictionary *)regions
1385 {
1386     WebView *wv = [_frame webView];
1387     id wd = [wv UIDelegate];
1388     
1389     [wv _addScrollerDashboardRegions:regions];
1390     
1391     if ([wd respondsToSelector: @selector(webView:dashboardRegionsChanged:)]) {
1392         [wd webView:wv dashboardRegionsChanged:regions];
1393     }
1394 }
1395
1396 // This method exists to hold localizable strings for action names for the Undo menu item. It contains
1397 // all of the names used in NSTextView. We will wire some or all of these up eventually; for now we are
1398 // just putting them here to get them localized before the localization freeze for Tiger.
1399 - (NSString *)setUndoActionNamePlaceholder
1400 {
1401     int x = 0;
1402     switch (x) {
1403         case 0: return UI_STRING_KEY("Set Color", "Set Color (Undo action name)", "Undo action name");
1404         case 1: return UI_STRING_KEY("Set Background Color", "Set Background Color (Undo action name)", "Undo action name");
1405         case 2: return UI_STRING_KEY("Turn Off Kerning", "Turn Off Kerning (Undo action name)", "Undo action name");
1406         case 3: return UI_STRING_KEY("Tighten Kerning", "Tighten Kerning (Undo action name)", "Undo action name");
1407         case 4: return UI_STRING_KEY("Loosen Kerning", "Loosen Kerning (Undo action name)", "Undo action name");
1408         case 5: return UI_STRING_KEY("Use Standard Kerning", "Use Standard Kerning (Undo action name)", "Undo action name");
1409         case 6: return UI_STRING_KEY("Turn Off Ligatures", "Turn Off Ligatures (Undo action name)", "Undo action name");
1410         case 7: return UI_STRING_KEY("Use Standard Ligatures", "Use Standard Ligatures (Undo action name)", "Undo action name");
1411         case 8: return UI_STRING_KEY("Use All Ligatures", "Use All Ligatures (Undo action name)", "Undo action name");
1412         case 9: return UI_STRING_KEY("Raise Baseline", "Raise Baseline (Undo action name)", "Undo action name");
1413         case 10: return UI_STRING_KEY("Lower Baseline", "Lower Baseline (Undo action name)", "Undo action name");
1414         case 11: return UI_STRING_KEY("Set Traditional Character Shape", "Set Traditional Character Shape (Undo action name)", "Undo action name");
1415         case 12: return UI_STRING_KEY("Set Font", "Set Font (Undo action name)", "Undo action name");
1416         case 13: return UI_STRING_KEY("Change Attributes", "Change Attributes (Undo action name)", "Undo action name");
1417         case 14: return UI_STRING_KEY("Align Left", "Align Left (Undo action name)", "Undo action name");
1418         case 15: return UI_STRING_KEY("Align Right", "Align Right (Undo action name)", "Undo action name");
1419         case 16: return UI_STRING_KEY("Center", "Center (Undo action name)", "Undo action name");
1420         case 17: return UI_STRING_KEY("Justify", "Justify (Undo action name)", "Undo action name");
1421         case 18: return UI_STRING_KEY("Set Writing Direction", "Set Writing Direction (Undo action name)", "Undo action name");
1422         case 19: return UI_STRING_KEY("Set Color", "Set Color (Undo action name)", "Undo action name");
1423         case 20: return UI_STRING_KEY("Subscript", "Subscript (Undo action name)", "Undo action name");
1424         case 21: return UI_STRING_KEY("Superscript", "Superscript (Undo action name)", "Undo action name");
1425         case 22: return UI_STRING_KEY("Underline", "Underline (Undo action name)", "Undo action name");
1426         case 23: return UI_STRING_KEY("Outline", "Outline (Undo action name)", "Undo action name");
1427         case 24: return UI_STRING_KEY("Unscript", "Unscript (Undo action name)", "Undo action name");
1428         case 25: return UI_STRING_KEY("Drag", "Drag (Undo action name)", "Undo action name");
1429         case 26: return UI_STRING_KEY("Cut", "Cut (Undo action name)", "Undo action name");
1430         case 27: return UI_STRING_KEY("Paste", "Paste (Undo action name)", "Undo action name");
1431         case 28: return UI_STRING_KEY("Paste Font", "Paste Font (Undo action name)", "Undo action name");
1432         case 29: return UI_STRING_KEY("Paste Ruler", "Paste Ruler (Undo action name)", "Undo action name");
1433         case 30: return UI_STRING_KEY("Cut", "Cut (Undo action name)", "Undo action name");
1434         case 31: return UI_STRING_KEY("Typing", "Typing (Undo action name)", "Undo action name");
1435     }
1436     return nil;
1437 }
1438
1439 @end