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