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