WebCore:
[WebKit-https.git] / WebKit / WebCoreSupport.subproj / WebBridge.m
1 /*      
2     WebBridge.m
3     Copyright (c) 2002, 2003, Apple Computer, Inc. All rights reserved.
4 */
5
6 #import <WebKit/WebBridge.h>
7
8 #import <WebKit/WebAssertions.h>
9 #import <WebKit/WebBackForwardList.h>
10 #import <WebKit/WebBaseNetscapePluginView.h>
11 #import <WebKit/WebBasePluginPackage.h>
12 #import <WebKit/WebBaseResourceHandleDelegate.h>
13 #import <WebKit/WebDataSourcePrivate.h>
14 #import <WebKit/WebDefaultUIDelegate.h>
15 #import <WebKit/WebEditingDelegate.h>
16 #import <WebKit/WebFileButton.h>
17 #import <WebKit/WebFormDataStream.h>
18 #import <WebKit/WebFormDelegate.h>
19 #import <WebKit/WebFrameInternal.h>
20 #import <WebKit/WebFrameLoadDelegate.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/WebResourcePrivate.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 - (BOOL)wasFirstResponderAtMouseDownTime:(NSResponder *)responder;
312 {
313     ASSERT(_frame != nil);
314     NSView *documentView = [[_frame frameView] documentView];
315     if (![documentView isKindOfClass:[WebHTMLView class]]) {
316         return NO;
317     }
318     WebHTMLView *webHTMLView = (WebHTMLView *)documentView;
319     return [webHTMLView _wasFirstResponderAtMouseDownTime:responder];
320 }
321
322 - (void)closeWindowSoon
323 {
324     [[_frame webView] performSelector:@selector(_closeWindow) withObject:nil afterDelay:0.0];
325 }
326
327 - (NSWindow *)window
328 {
329     ASSERT(_frame != nil);
330     return [[_frame frameView] window];
331 }
332
333 - (void)runJavaScriptAlertPanelWithMessage:(NSString *)message
334 {
335     WebView *wv = [_frame webView];
336     [[wv _UIDelegateForwarder] webView:wv runJavaScriptAlertPanelWithMessage:message];
337 }
338
339 - (BOOL)runJavaScriptConfirmPanelWithMessage:(NSString *)message
340 {
341     WebView *wv = [_frame webView];
342     id wd = [wv UIDelegate];
343     if ([wd respondsToSelector: @selector(webView:runJavaScriptConfirmPanelWithMessage:)])
344         return [wd webView:wv runJavaScriptConfirmPanelWithMessage:message];
345     return [[WebDefaultUIDelegate sharedUIDelegate] webView:wv runJavaScriptConfirmPanelWithMessage:message];
346 }
347
348 - (BOOL)runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText returningText:(NSString **)result
349 {
350     WebView *wv = [_frame webView];
351     id wd = [wv UIDelegate];
352     if ([wd respondsToSelector: @selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:)])
353         *result = [wd webView:wv runJavaScriptTextInputPanelWithPrompt:prompt defaultText:defaultText];
354     else
355         *result = [[WebDefaultUIDelegate sharedUIDelegate] webView:wv runJavaScriptTextInputPanelWithPrompt:prompt defaultText:defaultText];
356     return *result != nil;
357 }
358
359 - (void)addMessageToConsole:(NSDictionary *)message
360 {
361     WebView *wv = [_frame webView];
362     id wd = [wv UIDelegate];
363     if ([wd respondsToSelector: @selector(webView:addMessageToConsole:)])
364         [wd webView:wv addMessageToConsole:message];
365 }
366
367 - (NSView <WebCoreFileButton> *)fileButtonWithDelegate:(id <WebCoreFileButtonDelegate>)delegate
368 {
369     return [[WebFileButton alloc] initWithBridge:self delegate:delegate];
370 }
371
372 - (void)runOpenPanelForFileButtonWithResultListener:(id<WebOpenPanelResultListener>)resultListener
373 {
374     WebView *wv = [_frame webView];
375     [[wv _UIDelegateForwarder] webView:wv runOpenPanelForFileButtonWithResultListener:resultListener];
376 }
377
378
379 - (WebDataSource *)dataSource
380 {
381     ASSERT(_frame != nil);
382     WebDataSource *dataSource = [_frame dataSource];
383
384     ASSERT(dataSource != nil);
385     ASSERT([dataSource _isCommitted]);
386
387     return dataSource;
388 }
389
390 - (void)setTitle:(NSString *)title
391 {
392     [[self dataSource] _setTitle:[title _web_stringByCollapsingNonPrintingCharacters]];
393 }
394
395 - (void)setStatusText:(NSString *)status
396 {
397     ASSERT(_frame != nil);
398     WebView *wv = [_frame webView];
399     [[wv _UIDelegateForwarder] webView:wv setStatusText:status];
400 }
401
402 - (void)receivedData:(NSData *)data textEncodingName:(NSString *)textEncodingName
403 {
404     // Set the encoding. This only needs to be done once, but it's harmless to do it again later.
405     NSString *encoding = [[self dataSource] _overrideEncoding];
406     BOOL userChosen = encoding != nil;
407     if (encoding == nil) {
408         encoding = textEncodingName;
409     }
410     [self setEncoding:encoding userChosen:userChosen];
411
412     [self addData:data];
413 }
414
415 - (id <WebCoreResourceHandle>)startLoadingResource:(id <WebCoreResourceLoader>)resourceLoader withURL:(NSURL *)URL customHeaders:(NSDictionary *)customHeaders
416 {
417     // If we are no longer attached to a WebView, this must be an attempted load from an
418     // onUnload handler, so let's just block it.
419     if ([[self dataSource] _webView] == nil) {
420         return nil;
421     }
422
423     return [WebSubresourceClient startLoadingResource:resourceLoader
424                                               withURL:URL
425                                         customHeaders:customHeaders
426                                              referrer:[self referrer]
427                                         forDataSource:[self dataSource]];
428 }
429
430 - (id <WebCoreResourceHandle>)startLoadingResource:(id <WebCoreResourceLoader>)resourceLoader withURL:(NSURL *)URL customHeaders:(NSDictionary *)customHeaders postData:(NSArray *)postData
431 {
432     // If we are no longer attached to a WebView, this must be an attempted load from an
433     // onUnload handler, so let's just block it.
434     if ([[self dataSource] _webView] == nil) {
435         return nil;
436     }
437
438     return [WebSubresourceClient startLoadingResource:resourceLoader
439                                               withURL:URL
440                                         customHeaders:customHeaders
441                                              postData:postData
442                                              referrer:[self referrer]
443                                         forDataSource:[self dataSource]];
444 }
445
446 - (void)objectLoadedFromCacheWithURL:(NSURL *)URL response:(NSURLResponse *)response data:(NSData *)data
447 {
448     // Pass NO for copyData since the data doesn't need to be copied since it won't be modified. 
449     // Copying it will also cause a performance regression. 
450     WebResource *resource = [[WebResource alloc] _initWithData:data
451                                                            URL:URL
452                                                       MIMEType:[response MIMEType]
453                                               textEncodingName:[response textEncodingName]
454                                                      frameName:nil
455                                                       copyData:NO];
456     ASSERT(resource != nil);
457     [[self dataSource] addSubresource:resource];
458     [resource release];
459     
460     [_frame _sendResourceLoadDelegateMessagesForURL:URL response:response length:[data length]];    
461 }
462
463 - (NSData *)syncLoadResourceWithURL:(NSURL *)URL customHeaders:(NSDictionary *)requestHeaders postData:(NSArray *)postData finalURL:(NSURL **)finalURL responseHeaders:(NSDictionary **)responseHeaderDict statusCode:(int *)statusCode
464 {
465     NSMutableURLRequest *newRequest = [[NSMutableURLRequest alloc] initWithURL:URL];
466
467     if (postData) {
468         [newRequest setHTTPMethod:@"POST"];
469         webSetHTTPBody(newRequest, postData);
470     }
471
472     NSEnumerator *e = [requestHeaders keyEnumerator];
473     NSString *key;
474     while ((key = (NSString *)[e nextObject]) != nil) {
475         [newRequest addValue:[requestHeaders objectForKey:key] forHTTPHeaderField:key];
476     }
477     
478     // Never use cached data for these requests (xmlhttprequests).
479     [newRequest setCachePolicy:[[[self dataSource] request] cachePolicy]];
480     [newRequest setHTTPReferrer:[self referrer]];
481     
482     WebView *webView = [_frame webView];
483     [newRequest setMainDocumentURL:[[[[webView mainFrame] dataSource] request] URL]];
484     [newRequest setHTTPUserAgent:[webView userAgentForURL:[newRequest URL]]];
485
486     NSURLResponse *response = nil;
487     NSError *error = nil;
488     NSData *result = [NSURLConnection sendSynchronousRequest:newRequest returningResponse:&response error:&error];
489
490     if (error == nil) {
491         *finalURL = [response URL];
492         if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
493             NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; 
494             *responseHeaderDict = [httpResponse allHeaderFields];
495             *statusCode = [httpResponse statusCode];
496         } else {
497             *responseHeaderDict = [NSDictionary dictionary];
498             *statusCode = 200;
499         }
500
501         // notify the delegates
502         // FIXME: Bridge method name "loaded from cache" doesn't make any sense here.
503         [self objectLoadedFromCacheWithURL:URL response:response data:result];
504     } else {
505         *finalURL = URL;
506         *responseHeaderDict = [NSDictionary dictionary];
507         *statusCode = 404;
508     }
509
510     return result;
511 }
512
513 - (BOOL)isReloading
514 {
515     return [[[self dataSource] request] cachePolicy] == NSURLRequestReloadIgnoringCacheData;
516 }
517
518 // We would like a better value for a maximum time_t,
519 // but there is no way to do that in C with any certainty.
520 // INT_MAX should work well enough for our purposes.
521 #define MAX_TIME_T ((time_t)INT_MAX)    
522
523 - (time_t)expiresTimeForResponse:(NSURLResponse *)response
524 {
525     // This check can be removed when the new Foundation method
526     // has been around long enough for everyone to have it.
527     if ([response respondsToSelector:@selector(_calculatedExpiration)]) {
528         NSTimeInterval expiration = [response _calculatedExpiration];
529         expiration += kCFAbsoluteTimeIntervalSince1970;
530         return expiration > MAX_TIME_T ? MAX_TIME_T : expiration;
531     }
532
533     // Fall back to the older calculation
534     time_t now = time(NULL);
535     NSTimeInterval lifetime = [response _freshnessLifetime];
536     if (lifetime < 0)
537         lifetime = 0;
538     
539     if (now + lifetime > MAX_TIME_T)
540         return MAX_TIME_T;
541     
542     return now + lifetime;
543 }
544
545 - (void)reportClientRedirectToURL:(NSURL *)URL delay:(NSTimeInterval)seconds fireDate:(NSDate *)date lockHistory:(BOOL)lockHistory isJavaScriptFormAction:(BOOL)isJavaScriptFormAction
546 {
547     [_frame _clientRedirectedTo:URL delay:seconds fireDate:date lockHistory:lockHistory isJavaScriptFormAction:(BOOL)isJavaScriptFormAction];
548 }
549
550 - (void)reportClientRedirectCancelled:(BOOL)cancelWithLoadInProgress
551 {
552     [_frame _clientRedirectCancelled:cancelWithLoadInProgress];
553 }
554
555 - (void)close
556 {
557     _frame = nil;
558 }
559
560 - (void)focusWindow
561 {
562     [[[_frame webView] _UIDelegateForwarder] webViewFocus:[_frame webView]];
563 }
564
565 - (void)unfocusWindow
566 {
567     if ([[self window] isKeyWindow] || [[[self window] attachedSheet] isKeyWindow]) {
568         [NSApp _cycleWindowsReversed:FALSE];
569     }
570 }
571
572 - (void)setIconURL:(NSURL *)URL
573 {
574     [[self dataSource] _setIconURL:URL];
575 }
576
577 - (void)setIconURL:(NSURL *)URL withType:(NSString *)type
578 {
579     [[self dataSource] _setIconURL:URL withType:type];
580 }
581
582 - (BOOL)canTargetLoadInFrame:(WebFrame *)targetFrame
583 {
584     // This method prevents this exploit:
585     // <rdar://problem/3715785> multiple frame injection vulnerability reported by Secunia, affects almost all browsers
586     
587     // don't mess with navigation purely within the same frame
588     if ([[self webFrame] webView] == [targetFrame webView]) {
589         return YES;
590     }
591
592     // Normally, domain should be called on the DOMDocument since it is a DOM method, but this fix is needed for
593     // Jaguar as well where the DOM API doesn't exist.
594     NSString *thisDomain = [self domain];
595     if ([thisDomain length] == 0) {
596         // Allow if the request is made from a local file.
597         return YES;
598     }
599     
600     WebFrame *parentFrame = [targetFrame parentFrame];
601     if (parentFrame == nil) {
602         // Allow if target is an entire window.
603         return YES;
604     }
605     
606     NSString *parentDomain = [[parentFrame _bridge] domain];
607     if (parentDomain != nil && [thisDomain _web_isCaseInsensitiveEqualToString:parentDomain]) {
608         // Allow if the domain of the parent of the targeted frame equals this domain.
609         return YES;
610     }
611
612     return NO;
613 }
614
615 - (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
616 {
617     if ([target length] == 0) {
618         target = nil;
619     }
620
621     WebFrame *targetFrame = [_frame findFrameNamed:target];
622     if (![self canTargetLoadInFrame:targetFrame]) {
623         return;
624     }
625     
626     WebFrameLoadType loadType;
627     
628     if (reload)
629         loadType = WebFrameLoadTypeReload;
630     else if (!forUser)
631         loadType = WebFrameLoadTypeInternal;
632     else
633         loadType = WebFrameLoadTypeStandard;
634     [_frame _loadURL:URL referrer:referrer loadType:loadType target:target triggeringEvent:event form:form formValues:values];
635
636     if (targetFrame != nil && _frame != targetFrame) {
637         [[targetFrame _bridge] focusWindow];
638     }
639 }
640
641 - (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
642 {
643     if ([target length] == 0) {
644         target = nil;
645     }
646
647     WebFrame *targetFrame = [_frame findFrameNamed:target];
648     if (![self canTargetLoadInFrame:targetFrame]) {
649         return;
650     }
651
652     [_frame _postWithURL:URL referrer:referrer target:target data:postData contentType:contentType triggeringEvent:event form:form formValues:values];
653
654     if (targetFrame != nil && _frame != targetFrame) {
655         [[targetFrame _bridge] focusWindow];
656     }
657 }
658
659 - (NSString *)generateFrameName
660 {
661     return [_frame _generateFrameName];
662 }
663
664 - (WebCoreBridge *)createChildFrameNamed:(NSString *)frameName withURL:(NSURL *)URL
665     renderPart:(KHTMLRenderPart *)childRenderPart
666     allowsScrolling:(BOOL)allowsScrolling marginWidth:(int)width marginHeight:(int)height
667 {
668     ASSERT(_frame != nil);
669     WebFrame *newFrame = [[_frame webView] _createFrameNamed:frameName inParent:_frame allowsScrolling:allowsScrolling];
670     if (newFrame == nil) {
671         return nil;
672     }
673     
674     [[newFrame _bridge] setRenderPart:childRenderPart];
675
676     [[newFrame frameView] _setMarginWidth:width];
677     [[newFrame frameView] _setMarginHeight:height];
678
679     [_frame _loadURL:URL intoChild:newFrame];
680
681     return [newFrame _bridge];
682 }
683
684 - (void)saveDocumentState: (NSArray *)documentState
685 {
686     WebHistoryItem *item = [_frame _itemForSavingDocState];
687     LOG(Loading, "%@: saving form state from to 0x%x", [_frame name], item);
688     if (item) {
689         [item setDocumentState: documentState];
690         // You might think we could save the scroll state here too, but unfortunately this
691         // often gets called after WebFrame::_transitionToCommitted has restored the scroll
692         // position of the next document.
693     }
694 }
695
696 - (NSArray *)documentState
697 {
698     LOG(Loading, "%@: restoring form state from item 0x%x", [_frame name], [_frame _itemForRestoringDocState]);
699     return [[_frame _itemForRestoringDocState] documentState];
700 }
701
702 - (BOOL)saveDocumentToPageCache: documentInfo
703 {
704     WebHistoryItem *item = [_frame _itemForSavingDocState];
705     if (![item hasPageCache]) {
706         return false;
707     }
708     [[item pageCache] setObject: documentInfo forKey: WebCorePageCacheStateKey];
709     return true;
710 }
711
712 - (NSString *)userAgentForURL:(NSURL *)URL
713 {
714     return [[_frame webView] userAgentForURL:URL];
715 }
716
717 - (BOOL)inNextKeyViewOutsideWebFrameViews
718 {
719     return _inNextKeyViewOutsideWebFrameViews;
720 }
721
722 - (NSView *)nextKeyViewOutsideWebFrameViews
723 {
724     if (_inNextKeyViewOutsideWebFrameViews) {
725         // We should never get here, but unrepro bug 3997185 says we sometimes do.
726         // So we'll fail on debug builds to try to catch the problem, but on
727         // deployment builds we'll return nil to avoid recursing forever.
728         ASSERT_NOT_REACHED();
729         return nil;
730     }
731     
732     _inNextKeyViewOutsideWebFrameViews = YES;
733     WebView *webView = [_frame webView];
734     // Do not ask webView for its next key view, but rather, ask it for 
735     // the next key view of the last view in its key view loop.
736     // Doing so gives us the correct answer as calculated by AppKit, 
737     // and makes HTML views behave like other views.
738     NSView *nextKeyView = [[webView _findLastViewInKeyViewLoop] nextKeyView];
739     _inNextKeyViewOutsideWebFrameViews = NO;
740     return nextKeyView;
741 }
742
743 - (NSView *)previousKeyViewOutsideWebFrameViews
744 {
745     WebView *webView = [_frame webView];
746     NSView *previousKeyView = [webView previousKeyView];
747     return previousKeyView;
748 }
749
750 - (BOOL)defersLoading
751 {
752     return [[_frame webView] defersCallbacks];
753 }
754
755 - (void)setDefersLoading:(BOOL)defers
756 {
757     [[_frame webView] setDefersCallbacks:defers];
758 }
759
760 - (void)setNeedsReapplyStyles
761 {
762     NSView <WebDocumentView> *view = [[_frame frameView] documentView];
763     if ([view isKindOfClass:[WebHTMLView class]]) {
764         [(WebHTMLView *)view setNeedsToApplyStyles:YES];
765         [view setNeedsLayout:YES];
766         [view setNeedsDisplay:YES];
767     }
768 }
769
770 - (void)tokenizerProcessedData
771 {
772     [_frame _checkLoadComplete];
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 = [self baseURL];
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 - (WebPreferences *)_preferences
979 {
980     WebPreferences *prefs = [[_frame webView] preferences];
981     if (prefs == nil) {
982         prefs = [WebPreferences standardPreferences];
983     }
984     return prefs;
985 }
986
987 -(int)getObjectCacheSize
988 {
989     vm_size_t memSize = WebSystemMainMemory();
990     int cacheSize = [[self _preferences] _objectCacheSize];
991     int multiplier = 1;
992     if (memSize >= 1024 * 1024 * 1024)
993         multiplier = 4;
994     else if (memSize >= 512 * 1024 * 1024)
995         multiplier = 2;
996
997 #ifndef NDEBUG
998     if (!loggedObjectCacheSize){
999         LOG (CacheSizes, "Object cache size set to %d bytes.", cacheSize * multiplier);
1000         loggedObjectCacheSize = YES;
1001     }
1002 #endif
1003
1004     return cacheSize * multiplier;
1005 }
1006
1007 - (BOOL)frameRequiredForMIMEType:(NSString *)MIMEType URL:(NSURL *)URL
1008 {
1009     if ([MIMEType length] == 0) {
1010         NSString *extension = [[URL path] pathExtension];
1011         if ([extension length] > 0 && [[WebPluginDatabase installedPlugins] pluginForExtension:extension] != nil) {
1012             // If no MIME type is specified, use a plug-in if we have one that can handle the extension.
1013             return NO;
1014         } else {
1015             // Else, create a frame and attempt to load the URL in there.
1016             return YES;
1017         }
1018     }
1019     
1020     Class viewClass = [WebFrameView _viewClassForMIMEType:MIMEType];
1021     if (!viewClass) {
1022         // Want to display a "plugin not found" dialog/image, so let a plugin get made.
1023         return NO;
1024     }
1025         
1026     // If we're a supported type other than a plugin, we want to make a frame.
1027     // Ultimately we should just use frames for all mime types (plugins and HTML/XML/text documents),
1028     // but for now we're burdened with making a distinction between the two.
1029     return !([viewClass isSubclassOfClass:[WebNetscapePluginDocumentView class]] || 
1030              [viewClass isSubclassOfClass:[WebPluginDocumentView class]]);
1031 }
1032
1033 - (void)loadEmptyDocumentSynchronously
1034 {
1035     NSURL *url = [[NSURL alloc] initWithString:@""];
1036     NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
1037     [_frame loadRequest:request];
1038     [request release];
1039     [url release];
1040 }
1041
1042 - (NSString *)MIMETypeForPath:(NSString *)path
1043 {
1044     ASSERT(path);
1045     NSString *extension = [path pathExtension];
1046     NSString *type = [[NSURLFileTypeMappings sharedMappings] MIMETypeForExtension:extension];
1047     return [type length] == 0 ? @"application/octet-stream" : type;
1048 }
1049
1050 - (void)allowDHTMLDrag:(BOOL *)flagDHTML UADrag:(BOOL *)flagUA
1051 {
1052     WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
1053     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
1054     unsigned int mask = [docView _delegateDragSourceActionMask];
1055     *flagDHTML = (mask & WebDragSourceActionDHTML) != 0;
1056     *flagUA = ((mask & WebDragSourceActionImage) || (mask & WebDragSourceActionLink) || (mask & WebDragSourceActionSelection));
1057 }
1058
1059 - (BOOL)startDraggingImage:(NSImage *)dragImage at:(NSPoint)dragLoc operation:(NSDragOperation)op event:(NSEvent *)event sourceIsDHTML:(BOOL)flag DHTMLWroteData:(BOOL)dhtmlWroteData
1060 {
1061     WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
1062     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
1063     return [docView _startDraggingImage:dragImage at:dragLoc operation:op event:event sourceIsDHTML:flag DHTMLWroteData:dhtmlWroteData];
1064 }
1065
1066 - (void)handleAutoscrollForMouseDragged:(NSEvent *)event;
1067 {
1068     WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
1069
1070     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
1071
1072     [docView _handleAutoscrollForMouseDragged:event];
1073 }
1074
1075 - (BOOL)mayStartDragAtEventLocation:(NSPoint)location
1076 {
1077     WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
1078
1079     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
1080
1081     return [docView _mayStartDragAtEventLocation:location];
1082 }
1083
1084 - (BOOL)selectWordBeforeMenuEvent
1085 {
1086     return [[_frame webView] _selectWordBeforeMenuEvent];
1087 }
1088
1089 - (int)historyLength
1090 {
1091     return [[[_frame webView] backForwardList] backListCount] + 1;
1092 }
1093
1094 - (BOOL)canGoBackOrForward:(int)distance
1095 {
1096     if (distance == 0)
1097         return TRUE;
1098
1099     if (distance > 0 && distance <= [[[_frame webView] backForwardList] forwardListCount])
1100         return TRUE;
1101
1102     if (distance < 0 && -distance <= [[[_frame webView] backForwardList] backListCount])
1103         return TRUE;
1104     
1105     return FALSE;
1106 }
1107
1108 - (void)goBackOrForward:(int)distance
1109 {
1110     if (distance == 0) {
1111         return;
1112     }
1113     WebView *webView = [_frame webView];
1114     WebBackForwardList *list = [webView backForwardList];
1115     WebHistoryItem *item = [list itemAtIndex:distance];
1116     if (!item) {
1117         if (distance > 0) {
1118             int forwardListCount = [list forwardListCount];
1119             if (forwardListCount > 0) {
1120                 item = [list itemAtIndex:forwardListCount];
1121             }
1122         } else {
1123             int backListCount = [list forwardListCount];
1124             if (backListCount > 0) {
1125                 item = [list itemAtIndex:-backListCount];
1126             }
1127         }
1128     }
1129     if (item) {
1130         [webView goToBackForwardItem:item];
1131     }
1132 }
1133
1134 static id <WebFormDelegate> formDelegate(WebBridge *self)
1135 {
1136     ASSERT(self->_frame != nil);
1137     return [[self->_frame webView] _formDelegate];
1138 }
1139
1140 #define FormDelegateLog(ctrl)  LOG(FormDelegate, "control=%@", ctrl)
1141
1142 - (void)controlTextDidBeginEditing:(NSNotification *)obj
1143 {
1144     FormDelegateLog([obj object]);
1145     [formDelegate(self) controlTextDidBeginEditing:obj inFrame:_frame];
1146 }
1147
1148 - (void)controlTextDidEndEditing:(NSNotification *)obj
1149 {
1150     FormDelegateLog([obj object]);
1151     [formDelegate(self) controlTextDidEndEditing:obj inFrame:_frame];
1152 }
1153
1154 - (void)controlTextDidChange:(NSNotification *)obj
1155 {
1156     FormDelegateLog([obj object]);
1157     [formDelegate(self) controlTextDidChange:obj inFrame:_frame];
1158 }
1159
1160 - (BOOL)control:(NSControl *)control textShouldBeginEditing:(NSText *)fieldEditor
1161 {
1162     FormDelegateLog(control);
1163     return [formDelegate(self) control:control textShouldBeginEditing:fieldEditor inFrame:_frame];
1164 }
1165
1166 - (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor
1167 {
1168     FormDelegateLog(control);
1169     return [formDelegate(self) control:control textShouldEndEditing:fieldEditor inFrame:_frame];
1170 }
1171
1172 - (BOOL)control:(NSControl *)control didFailToFormatString:(NSString *)string errorDescription:(NSString *)error
1173 {
1174     FormDelegateLog(control);
1175     return [formDelegate(self) control:control didFailToFormatString:string errorDescription:error inFrame:_frame];
1176 }
1177
1178 - (void)control:(NSControl *)control didFailToValidatePartialString:(NSString *)string errorDescription:(NSString *)error
1179 {
1180     FormDelegateLog(control);
1181     [formDelegate(self) control:control didFailToValidatePartialString:string errorDescription:error inFrame:_frame];
1182 }
1183
1184 - (BOOL)control:(NSControl *)control isValidObject:(id)obj
1185 {
1186     FormDelegateLog(control);
1187     return [formDelegate(self) control:control isValidObject:obj inFrame:_frame];
1188 }
1189
1190 - (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector
1191 {
1192     FormDelegateLog(control);
1193     return [formDelegate(self) control:control textView:textView doCommandBySelector:commandSelector inFrame:_frame];
1194 }
1195
1196 - (BOOL)control:(NSControl *)control textView:(NSTextView *)textView shouldHandleEvent:(NSEvent *)event
1197 {
1198     FormDelegateLog(control);
1199     return [formDelegate(self) control:control textView:textView shouldHandleEvent:event inFrame:_frame];
1200 }
1201
1202 - (void)frameDetached
1203 {
1204     // Put _frame into a local variable because _detachFromParent
1205     // will disconnect the bridge from the frame and make _frame nil.
1206     WebFrame *frame = _frame;
1207
1208     [frame stopLoading];
1209     [frame _detachFromParent];
1210     [[frame parentFrame] _removeChild:frame];
1211 }
1212
1213 - (void)setHasBorder:(BOOL)hasBorder
1214 {
1215     [[_frame frameView] _setHasBorder:hasBorder];
1216 }
1217
1218 - (void)_retrieveKeyboardUIModeFromPreferences:(NSNotification *)notification
1219 {
1220     CFPreferencesAppSynchronize(UniversalAccessDomain);
1221
1222     BOOL keyExistsAndHasValidFormat;
1223     int mode = CFPreferencesGetAppIntegerValue(AppleKeyboardUIMode, UniversalAccessDomain, &keyExistsAndHasValidFormat);
1224     
1225     // The keyboard access mode is reported by two bits:
1226     // Bit 0 is set if feature is on
1227     // Bit 1 is set if full keyboard access works for any control, not just text boxes and lists
1228     // We require both bits to be on.
1229     // I do not know that we would ever get one bit on and the other off since
1230     // checking the checkbox in system preferences which is marked as "Turn on full keyboard access"
1231     // turns on both bits.
1232     _keyboardUIMode = (mode & 0x2) ? WebCoreKeyboardAccessFull : WebCoreKeyboardAccessDefault;
1233     
1234     // check for tabbing to links
1235     if ([[self _preferences] tabsToLinks]) {
1236         _keyboardUIMode |= WebCoreKeyboardAccessTabsToLinks;
1237     }
1238 }
1239
1240 - (WebCoreKeyboardUIMode)keyboardUIMode
1241 {
1242     if (!_keyboardUIModeAccessed) {
1243         _keyboardUIModeAccessed = YES;
1244         [self _retrieveKeyboardUIModeFromPreferences:nil];
1245         
1246         [[NSDistributedNotificationCenter defaultCenter] 
1247             addObserver:self selector:@selector(_retrieveKeyboardUIModeFromPreferences:) 
1248             name:KeyboardUIModeDidChangeNotification object:nil];
1249
1250         [[NSNotificationCenter defaultCenter] 
1251             addObserver:self selector:@selector(_retrieveKeyboardUIModeFromPreferences:) 
1252                    name:WebPreferencesChangedNotification object:nil];
1253     }
1254     return _keyboardUIMode;
1255 }
1256
1257 - (void)didSetName:(NSString *)name
1258 {
1259     [_frame _setName:name];
1260 }
1261
1262 - (NSFileWrapper *)fileWrapperForURL:(NSURL *)URL
1263 {
1264     return [[_frame dataSource] _fileWrapperForURL:URL];
1265 }
1266
1267 - (void)print
1268 {
1269     id wd = [[_frame webView] UIDelegate];
1270     
1271     if ([wd respondsToSelector:@selector(webView:printFrameView:)]) {
1272         [wd webView:[_frame webView] printFrameView:[_frame frameView]];
1273     } else if ([wd respondsToSelector:@selector(webViewPrint:)]) {
1274         // Backward-compatible, but webViewPrint: was never public, so probably not needed.
1275         [wd webViewPrint:[_frame webView]];
1276     } else {
1277         [[WebDefaultUIDelegate sharedUIDelegate] webView:[_frame webView] printFrameView:[_frame frameView]];
1278     }
1279 }
1280
1281 - (jobject)getAppletInView:(NSView *)view
1282 {
1283     jobject applet = 0;
1284
1285     if ([view respondsToSelector: @selector(webPlugInGetApplet)])
1286         applet = [view webPlugInGetApplet];
1287     else
1288         applet = [self pollForAppletInView:view];
1289         
1290     return applet;
1291 }
1292
1293 // NOTE: pollForAppletInView: will block until the block is ready to use, or
1294 // until a timeout is exceeded.  It will return nil if the timeour is
1295 // exceeded.
1296 // Deprecated, use getAppletInView:.
1297 - (jobject)pollForAppletInView: (NSView *)view
1298 {
1299     jobject applet = 0;
1300     
1301     if ([view respondsToSelector: @selector(pollForAppletInWindow:)]) {
1302         // The Java VM needs the containing window of the view to
1303         // initialize.  The view may not yet be in the window's view 
1304         // hierarchy, so we have to pass the window when requesting
1305         // the applet.
1306         applet = [view pollForAppletInWindow:[[_frame webView] window]];
1307     }
1308     
1309     return applet;
1310 }
1311
1312 - (void)respondToChangedContents
1313 {
1314     NSView <WebDocumentView> *view = [[_frame frameView] documentView];
1315     if ([view isKindOfClass:[WebHTMLView class]]) {
1316         [(WebHTMLView *)view _updateFontPanel];
1317     }
1318     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewDidChangeNotification object:[_frame webView]];
1319 }
1320
1321 - (void)respondToChangedSelection
1322 {
1323     NSView <WebDocumentView> *view = [[_frame frameView] documentView];
1324     if ([view isKindOfClass:[WebHTMLView class]]) {
1325         [(WebHTMLView *)view _selectionChanged];
1326     }
1327     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewDidChangeSelectionNotification object:[_frame webView]];
1328 }
1329
1330 - (NSUndoManager *)undoManager
1331 {
1332     return [[_frame webView] undoManager];
1333 }
1334
1335 - (void)issueCutCommand
1336 {
1337     [[_frame webView] cut:nil];
1338 }
1339
1340 - (void)issueCopyCommand
1341 {
1342     [[_frame webView] copy:nil];
1343 }
1344
1345 - (void)issuePasteCommand
1346 {
1347     [[_frame webView] paste:nil];
1348 }
1349
1350 - (void)issuePasteAndMatchStyleCommand
1351 {
1352     [[_frame webView] pasteAsPlainText:nil];
1353 }
1354
1355 - (BOOL)canPaste
1356 {
1357     return [[_frame webView] _canPaste];
1358 }
1359
1360 - (void)setIsSelected:(BOOL)isSelected forView:(NSView *)view
1361 {
1362     if ([view respondsToSelector:@selector(webPlugInSetIsSelected:)]) {
1363         [view webPlugInSetIsSelected:isSelected];
1364     }
1365     else if ([view respondsToSelector:@selector(setIsSelected:)]) {
1366         [view setIsSelected:isSelected];
1367     }
1368 }
1369
1370 - (NSString *)overrideMediaType
1371 {
1372     return [[_frame webView] mediaStyle];
1373 }
1374
1375 - (BOOL)isEditable
1376 {
1377     return [[_frame webView] isEditable];
1378 }
1379
1380 - (BOOL)shouldBeginEditing:(DOMRange *)range
1381 {
1382     return [[_frame webView] _shouldBeginEditingInDOMRange:range];
1383 }
1384
1385 - (BOOL)shouldEndEditing:(DOMRange *)range
1386 {
1387     return [[_frame webView] _shouldEndEditingInDOMRange:range];
1388 }
1389
1390 - (void)windowObjectCleared
1391 {
1392     WebView *wv = [_frame webView];
1393     [[wv _frameLoadDelegateForwarder] webView:wv windowScriptObjectAvailable:[self windowScriptObject]];
1394 }
1395
1396 - (int)spellCheckerDocumentTag
1397 {
1398     return [[_frame webView] spellCheckerDocumentTag];
1399 }
1400
1401 - (BOOL)isContinuousSpellCheckingEnabled
1402 {
1403     return [[_frame webView] isContinuousSpellCheckingEnabled];
1404 }
1405
1406 - (void)didFirstLayout
1407 {
1408     WebView *wv = [_frame webView];
1409     [[wv _frameLoadDelegateForwarder] webView:wv didFirstLayoutInFrame:_frame];
1410 }
1411
1412 - (void)dashboardRegionsChanged:(NSMutableDictionary *)regions
1413 {
1414     WebView *wv = [_frame webView];
1415     id wd = [wv UIDelegate];
1416     
1417     [wv _addScrollerDashboardRegions:regions];
1418     
1419     if ([wd respondsToSelector: @selector(webView:dashboardRegionsChanged:)]) {
1420         [wd webView:wv dashboardRegionsChanged:regions];
1421     }
1422 }
1423
1424 - (NSString *)nameForUndoAction:(WebUndoAction)undoAction
1425 {
1426     switch (undoAction) {
1427         case WebUndoActionUnspecified: return nil;
1428         case WebUndoActionSetColor: return UI_STRING_KEY("Set Color", "Set Color (Undo action name)", "Undo action name");
1429         case WebUndoActionSetBackgroundColor: return UI_STRING_KEY("Set Background Color", "Set Background Color (Undo action name)", "Undo action name");
1430         case WebUndoActionTurnOffKerning: return UI_STRING_KEY("Turn Off Kerning", "Turn Off Kerning (Undo action name)", "Undo action name");
1431         case WebUndoActionTightenKerning: return UI_STRING_KEY("Tighten Kerning", "Tighten Kerning (Undo action name)", "Undo action name");
1432         case WebUndoActionLoosenKerning: return UI_STRING_KEY("Loosen Kerning", "Loosen Kerning (Undo action name)", "Undo action name");
1433         case WebUndoActionUseStandardKerning: return UI_STRING_KEY("Use Standard Kerning", "Use Standard Kerning (Undo action name)", "Undo action name");
1434         case WebUndoActionTurnOffLigatures: return UI_STRING_KEY("Turn Off Ligatures", "Turn Off Ligatures (Undo action name)", "Undo action name");
1435         case WebUndoActionUseStandardLigatures: return UI_STRING_KEY("Use Standard Ligatures", "Use Standard Ligatures (Undo action name)", "Undo action name");
1436         case WebUndoActionUseAllLigatures: return UI_STRING_KEY("Use All Ligatures", "Use All Ligatures (Undo action name)", "Undo action name");
1437         case WebUndoActionRaiseBaseline: return UI_STRING_KEY("Raise Baseline", "Raise Baseline (Undo action name)", "Undo action name");
1438         case WebUndoActionLowerBaseline: return UI_STRING_KEY("Lower Baseline", "Lower Baseline (Undo action name)", "Undo action name");
1439         case WebUndoActionSetTraditionalCharacterShape: return UI_STRING_KEY("Set Traditional Character Shape", "Set Traditional Character Shape (Undo action name)", "Undo action name");
1440         case WebUndoActionSetFont: return UI_STRING_KEY("Set Font", "Set Font (Undo action name)", "Undo action name");
1441         case WebUndoActionChangeAttributes: return UI_STRING_KEY("Change Attributes", "Change Attributes (Undo action name)", "Undo action name");
1442         case WebUndoActionAlignLeft: return UI_STRING_KEY("Align Left", "Align Left (Undo action name)", "Undo action name");
1443         case WebUndoActionAlignRight: return UI_STRING_KEY("Align Right", "Align Right (Undo action name)", "Undo action name");
1444         case WebUndoActionCenter: return UI_STRING_KEY("Center", "Center (Undo action name)", "Undo action name");
1445         case WebUndoActionJustify: return UI_STRING_KEY("Justify", "Justify (Undo action name)", "Undo action name");
1446         case WebUndoActionSetWritingDirection: return UI_STRING_KEY("Set Writing Direction", "Set Writing Direction (Undo action name)", "Undo action name");
1447         case WebUndoActionSubscript: return UI_STRING_KEY("Subscript", "Subscript (Undo action name)", "Undo action name");
1448         case WebUndoActionSuperscript: return UI_STRING_KEY("Superscript", "Superscript (Undo action name)", "Undo action name");
1449         case WebUndoActionUnderline: return UI_STRING_KEY("Underline", "Underline (Undo action name)", "Undo action name");
1450         case WebUndoActionOutline: return UI_STRING_KEY("Outline", "Outline (Undo action name)", "Undo action name");
1451         case WebUndoActionUnscript: return UI_STRING_KEY("Unscript", "Unscript (Undo action name)", "Undo action name");
1452         case WebUndoActionDrag: return UI_STRING_KEY("Drag", "Drag (Undo action name)", "Undo action name");
1453         case WebUndoActionCut: return UI_STRING_KEY("Cut", "Cut (Undo action name)", "Undo action name");
1454         case WebUndoActionPaste: return UI_STRING_KEY("Paste", "Paste (Undo action name)", "Undo action name");
1455         case WebUndoActionPasteFont: return UI_STRING_KEY("Paste Font", "Paste Font (Undo action name)", "Undo action name");
1456         case WebUndoActionPasteRuler: return UI_STRING_KEY("Paste Ruler", "Paste Ruler (Undo action name)", "Undo action name");
1457         case WebUndoActionTyping: return UI_STRING_KEY("Typing", "Typing (Undo action name)", "Undo action name");
1458     }
1459     return nil;
1460 }
1461
1462 // FIXME: The following 2 functions are copied from AppKit. It would be best share code.
1463
1464 // MF:!!! For now we will use static character sets for the computation, but we should eventually probably make these keys in the language dictionaries.
1465 // MF:!!! The following characters (listed with their nextstep encoding values) were in the preSmartTable in the old text objet, but aren't yet in the new text object: NS_FIGSPACE (0x80), exclamdown (0xa1), sterling (0xa3), yen (0xa5), florin (0xa6) section (0xa7), currency (0xa8), quotesingle (0xa9), quotedblleft (0xaa), guillemotleft (0xab), guilsinglleft (0xac), endash (0xb1), quotesinglbase (0xb8), quotedblbase (0xb9), questiondown (0xbf), emdash (0xd0), plusminus (0xd1).
1466 // MF:!!! The following characters (listed with their nextstep encoding values) were in the postSmartTable in the old text objet, but aren't yet in the new text object: NS_FIGSPACE (0x80), cent (0xa2), guilsinglright (0xad), registered (0xb0), dagger (0xa2), daggerdbl (0xa3), endash (0xb1), quotedblright (0xba), guillemotright (0xbb), perthousand (0xbd), onesuperior (0xc0), twosuperior (0xc9), threesuperior (0xcc), emdash (0xd0), ordfeminine (0xe3), ordmasculine (0xeb).
1467 // MF:!!! Another difference in both of these sets from the old text object is we include all the whitespace in whitespaceAndNewlineCharacterSet.
1468 #define _preSmartString @"([\"\'#$/-`{"
1469 #define _postSmartString @")].,;:?\'!\"%*-/}"
1470
1471 static NSCharacterSet *_getPreSmartSet(void)
1472 {
1473     static NSMutableCharacterSet *_preSmartSet = nil;
1474     if (!_preSmartSet) {
1475         _preSmartSet = [[NSMutableCharacterSet characterSetWithCharactersInString:_preSmartString] retain];
1476         [_preSmartSet formUnionWithCharacterSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
1477         // Adding CJK ranges
1478         [_preSmartSet addCharactersInRange:NSMakeRange(0x1100, 256)]; // Hangul Jamo (0x1100 - 0x11FF)
1479         [_preSmartSet addCharactersInRange:NSMakeRange(0x2E80, 352)]; // CJK & Kangxi Radicals (0x2E80 - 0x2FDF)
1480         [_preSmartSet addCharactersInRange:NSMakeRange(0x2FF0, 464)]; // Ideograph Descriptions, CJK Symbols, Hiragana, Katakana, Bopomofo, Hangul Compatibility Jamo, Kanbun, & Bopomofo Ext (0x2FF0 - 0x31BF)
1481         [_preSmartSet addCharactersInRange:NSMakeRange(0x3200, 29392)]; // Enclosed CJK, CJK Ideographs (Uni Han & Ext A), & Yi (0x3200 - 0xA4CF)
1482         [_preSmartSet addCharactersInRange:NSMakeRange(0xAC00, 11183)]; // Hangul Syllables (0xAC00 - 0xD7AF)
1483         [_preSmartSet addCharactersInRange:NSMakeRange(0xF900, 352)]; // CJK Compatibility Ideographs (0xF900 - 0xFA5F)
1484         [_preSmartSet addCharactersInRange:NSMakeRange(0xFE30, 32)]; // CJK Compatibility From (0xFE30 - 0xFE4F)
1485         [_preSmartSet addCharactersInRange:NSMakeRange(0xFF00, 240)]; // Half/Full Width Form (0xFF00 - 0xFFEF)
1486         [_preSmartSet addCharactersInRange:NSMakeRange(0x20000, 0xA6D7)]; // CJK Ideograph Exntension B
1487         [_preSmartSet addCharactersInRange:NSMakeRange(0x2F800, 0x021E)]; // CJK Compatibility Ideographs (0x2F800 - 0x2FA1D)
1488     }
1489     return _preSmartSet;
1490 }
1491
1492 static NSCharacterSet *_getPostSmartSet(void)
1493 {
1494     static NSMutableCharacterSet *_postSmartSet = nil;
1495     if (!_postSmartSet) {
1496         _postSmartSet = [[NSMutableCharacterSet characterSetWithCharactersInString:_postSmartString] retain];
1497         [_postSmartSet formUnionWithCharacterSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
1498         [_postSmartSet addCharactersInRange:NSMakeRange(0x1100, 256)]; // Hangul Jamo (0x1100 - 0x11FF)
1499         [_postSmartSet addCharactersInRange:NSMakeRange(0x2E80, 352)]; // CJK & Kangxi Radicals (0x2E80 - 0x2FDF)
1500         [_postSmartSet addCharactersInRange:NSMakeRange(0x2FF0, 464)]; // Ideograph Descriptions, CJK Symbols, Hiragana, Katakana, Bopomofo, Hangul Compatibility Jamo, Kanbun, & Bopomofo Ext (0x2FF0 - 0x31BF)
1501         [_postSmartSet addCharactersInRange:NSMakeRange(0x3200, 29392)]; // Enclosed CJK, CJK Ideographs (Uni Han & Ext A), & Yi (0x3200 - 0xA4CF)
1502         [_postSmartSet addCharactersInRange:NSMakeRange(0xAC00, 11183)]; // Hangul Syllables (0xAC00 - 0xD7AF)
1503         [_postSmartSet addCharactersInRange:NSMakeRange(0xF900, 352)]; // CJK Compatibility Ideographs (0xF900 - 0xFA5F)
1504         [_postSmartSet addCharactersInRange:NSMakeRange(0xFE30, 32)]; // CJK Compatibility From (0xFE30 - 0xFE4F)
1505         [_postSmartSet addCharactersInRange:NSMakeRange(0xFF00, 240)]; // Half/Full Width Form (0xFF00 - 0xFFEF)
1506         [_postSmartSet addCharactersInRange:NSMakeRange(0x20000, 0xA6D7)]; // CJK Ideograph Exntension B
1507         [_postSmartSet addCharactersInRange:NSMakeRange(0x2F800, 0x021E)]; // CJK Compatibility Ideographs (0x2F800 - 0x2FA1D)        
1508         [_postSmartSet formUnionWithCharacterSet:[NSCharacterSet punctuationCharacterSet]];
1509     }
1510     return _postSmartSet;
1511 }
1512
1513 - (BOOL)isCharacterSmartReplaceExempt:(unichar)c isPreviousCharacter:(BOOL)isPreviousCharacter
1514 {
1515     return [isPreviousCharacter ? _getPreSmartSet() : _getPostSmartSet() characterIsMember:c];
1516 }
1517
1518 @end