WebCore:
[WebKit-https.git] / WebKit / WebCoreSupport / WebFrameBridge.m
1 /*
2  * Copyright (C) 2005, 2006 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer. 
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution. 
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission. 
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #import "WebFrameBridge.h"
30
31 #import <JavaScriptCore/Assertions.h>
32 #import "WebBackForwardList.h"
33 #import "WebBaseNetscapePluginView.h"
34 #import "WebBasePluginPackage.h"
35 #import "WebDataSourcePrivate.h"
36 #import "WebDefaultUIDelegate.h"
37 #import "WebEditingDelegate.h"
38 #import "WebFormDataStream.h"
39 #import "WebFormDelegate.h"
40 #import "WebFrameInternal.h"
41 #import "WebFrameLoadDelegate.h"
42 #import "WebFrameViewInternal.h"
43 #import "WebHTMLRepresentationPrivate.h"
44 #import "WebHTMLViewInternal.h"
45 #import "WebHistoryItemPrivate.h"
46 #import "WebImageView.h"
47 #import "WebJavaPlugIn.h"
48 #import "WebJavaScriptTextInputPanel.h"
49 #import "WebKitErrorsPrivate.h"
50 #import "WebKitLogging.h"
51 #import "WebKitNSStringExtras.h"
52 #import "WebKitStatisticsPrivate.h"
53 #import "WebKitSystemBits.h"
54 #import "WebLoader.h"
55 #import "WebLocalizableStrings.h"
56 #import "WebNSObjectExtras.h"
57 #import "WebNSURLExtras.h"
58 #import "WebNSURLRequestExtras.h"
59 #import "WebNSViewExtras.h"
60 #import "WebNetscapePluginDocumentView.h"
61 #import "WebNetscapePluginEmbeddedView.h"
62 #import "WebNetscapePluginPackage.h"
63 #import "WebNullPluginView.h"
64 #import "WebPageBridge.h"
65 #import "WebPlugin.h"
66 #import "WebPluginController.h"
67 #import "WebPluginDatabase.h"
68 #import "WebPluginDocumentView.h"
69 #import "WebPluginPackage.h"
70 #import "WebPluginViewFactoryPrivate.h"
71 #import "WebPreferencesPrivate.h"
72 #import "WebResourcePrivate.h"
73 #import "WebSubresourceLoader.h"
74 #import "WebUIDelegatePrivate.h"
75 #import "WebViewInternal.h"
76 #import <Foundation/NSURLConnection.h>
77 #import <Foundation/NSURLRequest.h>
78 #import <Foundation/NSURLResponse.h>
79 #import <JavaVM/jni.h>
80 #import <WebCore/WebCoreFrameNamespaces.h>
81 #import <WebKitSystemInterface.h>
82
83 // For compatibility only with old SPI. 
84 @interface NSObject (OldWebPlugin)
85 - (void)setIsSelected:(BOOL)f;
86 @end
87
88 @interface NSApplication (DeclarationStolenFromAppKit)
89 - (void)_cycleWindowsReversed:(BOOL)reversed;
90 @end
91
92 @interface NSView (AppKitSecretsWebBridgeKnowsAbout)
93 - (NSView *)_findLastViewInKeyViewLoop;
94 @end
95
96 @interface NSURLResponse (FoundationSecretsWebBridgeKnowsAbout)
97 - (NSTimeInterval)_calculatedExpiration;
98 @end
99
100 @interface NSView (JavaPluginSecrets)
101 - (jobject)pollForAppletInWindow:(NSWindow *)window;
102 @end
103
104 NSString *WebPluginBaseURLKey =     @"WebPluginBaseURL";
105 NSString *WebPluginAttributesKey =  @"WebPluginAttributes";
106 NSString *WebPluginContainerKey =   @"WebPluginContainer";
107
108 @implementation WebFrameBridge
109
110 - (WebView *)webView
111 {
112     ASSERT([[self page] isKindOfClass:[WebPageBridge class]]);
113     return [(WebPageBridge *)[self page] webView];
114 }
115
116 - (id)initMainFrameWithPage:(WebPageBridge *)page frameName:(NSString *)name view:(WebFrameView *)view
117 {
118     self = [super initMainFrameWithPage:page];
119
120     ++WebBridgeCount;
121     
122     _frame = [[WebFrame alloc] _initWithWebFrameView:view webView:[self webView] bridge:self];
123
124     [self setName:name];
125     [self initializeSettings:[[self webView] _settings]];
126     [self setTextSizeMultiplier:[[self webView] textSizeMultiplier]];
127
128     return self;
129 }
130
131 - (id)initSubframeWithRenderer:(WebCoreRenderPart *)renderer frameName:(NSString *)name view:(WebFrameView *)view
132 {
133     self = [super initSubframeWithRenderer:renderer];
134
135     ++WebBridgeCount;
136     
137     _frame = [[WebFrame alloc] _initWithWebFrameView:view webView:[self webView] bridge:self];
138
139     [self setName:name];
140     [self initializeSettings:[[self webView] _settings]];
141     [self setTextSizeMultiplier:[[self webView] textSizeMultiplier]];
142
143     return self;
144 }
145
146 - (void)fini
147 {
148     ASSERT(_frame == nil);
149     --WebBridgeCount;
150 }
151
152 - (void)dealloc
153 {
154     [lastDashboardRegions release];
155     [_frame release];
156     
157     [self fini];
158     [super dealloc];
159 }
160
161 - (void)finalize
162 {
163     [self fini];
164     [super finalize];
165 }
166
167 - (WebFrame *)webFrame
168 {
169     return _frame;
170 }
171
172 - (WebCoreFrameBridge *)mainFrame
173 {
174     ASSERT(_frame != nil);
175     return [[[self webView] mainFrame] _bridge];
176 }
177
178 - (NSView *)documentView
179 {
180     ASSERT(_frame != nil);
181     return [[_frame frameView] documentView];
182 }
183
184 - (WebCorePageBridge *)createWindowWithURL:(NSURL *)URL
185 {
186     ASSERT(_frame != nil);
187
188     NSMutableURLRequest *request = nil;
189     if (URL != nil && ![URL _web_isEmpty]) {
190         request = [NSMutableURLRequest requestWithURL:URL];
191         [request _web_setHTTPReferrer:[self referrer]];
192     }
193
194     WebView *currentWebView = [self webView];
195     id wd = [currentWebView UIDelegate];
196     WebView *newWebView;
197     if ([wd respondsToSelector:@selector(webView:createWebViewWithRequest:)])
198         newWebView = [wd webView:currentWebView createWebViewWithRequest:request];
199     else
200         newWebView = [[WebDefaultUIDelegate sharedUIDelegate] webView:currentWebView createWebViewWithRequest:request];
201     return [newWebView _pageBridge];
202 }
203
204 - (void)showWindow
205 {
206     WebView *wv = [self webView];
207     [[wv _UIDelegateForwarder] webViewShow:wv];
208 }
209
210 - (BOOL)areToolbarsVisible
211 {
212     ASSERT(_frame != nil);
213     WebView *wv = [self 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 = [self 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 = [self 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 = [self webView];
253     [[wv _UIDelegateForwarder] webView:wv setStatusBarVisible:visible];
254 }
255
256 - (void)setWindowIsResizable:(BOOL)resizable
257 {
258     ASSERT(_frame != nil);
259     WebView *webView = [self webView];
260     [[webView _UIDelegateForwarder] webView:webView setResizable:resizable];
261 }
262
263 - (BOOL)windowIsResizable
264 {
265     ASSERT(_frame != nil);
266     WebView *webView = [self webView];
267     return [[webView _UIDelegateForwarder] webViewIsResizable:webView];
268 }
269
270 - (NSResponder *)firstResponder
271 {
272     ASSERT(_frame != nil);
273     WebView *webView = [self webView];
274     return [[webView _UIDelegateForwarder] webViewFirstResponder:webView];
275 }
276
277 - (void)makeFirstResponder:(NSResponder *)view
278 {
279     ASSERT(_frame != nil);
280     WebView *webView = [self webView];
281     [webView _pushPerformingProgrammaticFocus];
282     [[webView _UIDelegateForwarder] webView:webView makeFirstResponder:view];
283     [webView _popPerformingProgrammaticFocus];
284 }
285
286 - (void)willMakeFirstResponderForNodeFocus
287 {
288     ASSERT([[[_frame frameView] documentView] isKindOfClass:[WebHTMLView class]]);
289     [(WebHTMLView *)[[_frame frameView] documentView] _willMakeFirstResponderForNodeFocus];
290 }
291
292
293 - (BOOL)wasFirstResponderAtMouseDownTime:(NSResponder *)responder;
294 {
295     ASSERT(_frame != nil);
296     NSView *documentView = [[_frame frameView] documentView];
297     if (![documentView isKindOfClass:[WebHTMLView class]]) {
298         return NO;
299     }
300     WebHTMLView *webHTMLView = (WebHTMLView *)documentView;
301     return [webHTMLView _wasFirstResponderAtMouseDownTime:responder];
302 }
303
304 - (void)closeWindowSoon
305 {
306     WebView *parentWebView = [self webView];
307
308     // We need to remove the parent WebView from WebViewSets here, before it actually
309     // closes, to make sure that JavaScript code that executes before it closes
310     // can't find it. Otherwise, window.open will select a closed WebView instead of 
311     // opening a new one <rdar://problem/3572585>.
312
313     // We also need to stop the load to prevent further parsing or JavaScript execution
314     // after the window has torn down <rdar://problem/4161660>.
315   
316     // FIXME: This code assumes that the UI delegate will respond to a webViewClose
317     // message by actually closing the WebView. Safari guarantees this behavior, but other apps might not.
318     // This approach is an inherent limitation of not making a close execute immediately
319     // after a call to window.close.
320     
321     [parentWebView setGroupName:nil];
322     [parentWebView stopLoading:self];
323     [parentWebView performSelector:@selector(_closeWindow) withObject:nil afterDelay:0.0];
324 }
325
326 - (NSWindow *)window
327 {
328     ASSERT(_frame != nil);
329     return [[_frame frameView] window];
330 }
331
332 - (void)runJavaScriptAlertPanelWithMessage:(NSString *)message
333 {
334     WebView *wv = [self webView];
335     id wd = [wv UIDelegate];
336     // Check whether delegate implements new version, then whether delegate implements old version. If neither,
337     // fall back to shared delegate's implementation of new version.
338     if ([wd respondsToSelector:@selector(webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:)])
339         [wd webView:wv runJavaScriptAlertPanelWithMessage:message initiatedByFrame:_frame];
340     else if ([wd respondsToSelector:@selector(webView:runJavaScriptAlertPanelWithMessage:)])
341         [wd webView:wv runJavaScriptAlertPanelWithMessage:message];
342     else
343         [[WebDefaultUIDelegate sharedUIDelegate] webView:wv runJavaScriptAlertPanelWithMessage:message initiatedByFrame:_frame];
344 }
345
346 - (BOOL)runJavaScriptConfirmPanelWithMessage:(NSString *)message
347 {
348     WebView *wv = [self webView];
349     id wd = [wv UIDelegate];
350     // Check whether delegate implements new version, then whether delegate implements old version. If neither,
351     // fall back to shared delegate's implementation of new version.
352     if ([wd respondsToSelector:@selector(webView:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:)])
353         return [wd webView:wv runJavaScriptConfirmPanelWithMessage:message initiatedByFrame:_frame];
354     if ([wd respondsToSelector:@selector(webView:runJavaScriptConfirmPanelWithMessage:)])
355         return [wd webView:wv runJavaScriptConfirmPanelWithMessage:message];    
356     return [[WebDefaultUIDelegate sharedUIDelegate] webView:wv runJavaScriptConfirmPanelWithMessage:message initiatedByFrame:_frame];
357 }
358
359 - (BOOL)canRunBeforeUnloadConfirmPanel
360 {
361     WebView *wv = [self webView];
362     id wd = [wv UIDelegate];
363     return [wd respondsToSelector:@selector(webView:runBeforeUnloadConfirmPanelWithMessage:initiatedByFrame:)];
364 }
365
366 - (BOOL)runBeforeUnloadConfirmPanelWithMessage:(NSString *)message
367 {
368     WebView *wv = [self webView];
369     id wd = [wv UIDelegate];
370     if ([wd respondsToSelector:@selector(webView:runBeforeUnloadConfirmPanelWithMessage:initiatedByFrame:)])
371         return [wd webView:wv runBeforeUnloadConfirmPanelWithMessage:message initiatedByFrame:_frame];
372     return YES;
373 }
374
375 - (BOOL)runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText returningText:(NSString **)result
376 {
377     WebView *wv = [self webView];
378     id wd = [wv UIDelegate];
379     // Check whether delegate implements new version, then whether delegate implements old version. If neither,
380     // fall back to shared delegate's implementation of new version.
381     if ([wd respondsToSelector:@selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:)])
382         *result = [wd webView:wv runJavaScriptTextInputPanelWithPrompt:prompt defaultText:defaultText initiatedByFrame:_frame];
383     else if ([wd respondsToSelector:@selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:)])
384         *result = [wd webView:wv runJavaScriptTextInputPanelWithPrompt:prompt defaultText:defaultText];
385     else
386         *result = [[WebDefaultUIDelegate sharedUIDelegate] webView:wv runJavaScriptTextInputPanelWithPrompt:prompt defaultText:defaultText initiatedByFrame:_frame];
387     return *result != nil;
388 }
389
390 - (void)addMessageToConsole:(NSDictionary *)message
391 {
392     WebView *wv = [self webView];
393     id wd = [wv UIDelegate];
394     if ([wd respondsToSelector:@selector(webView:addMessageToConsole:)])
395         [wd webView:wv addMessageToConsole:message];
396 }
397
398 - (void)runOpenPanelForFileButtonWithResultListener:(id<WebCoreOpenPanelResultListener>)resultListener
399 {
400     WebView *wv = [self webView];
401     [[wv _UIDelegateForwarder] webView:wv runOpenPanelForFileButtonWithResultListener:(id<WebOpenPanelResultListener>)resultListener];
402 }
403
404 - (WebDataSource *)dataSource
405 {
406     ASSERT(_frame != nil);
407     WebDataSource *dataSource = [_frame dataSource];
408
409     ASSERT(dataSource != nil);
410     ASSERT([dataSource _isCommitted]);
411
412     return dataSource;
413 }
414
415 - (void)setTitle:(NSString *)title
416 {
417     [[self dataSource] _setTitle:[title _webkit_stringByCollapsingNonPrintingCharacters]];
418 }
419
420 - (void)setStatusText:(NSString *)status
421 {
422     ASSERT(_frame != nil);
423     WebView *wv = [self webView];
424     [[wv _UIDelegateForwarder] webView:wv setStatusText:status];
425 }
426
427 - (void)receivedData:(NSData *)data textEncodingName:(NSString *)textEncodingName
428 {
429     // Set the encoding. This only needs to be done once, but it's harmless to do it again later.
430     NSString *encoding = [[self dataSource] _overrideEncoding];
431     BOOL userChosen = encoding != nil;
432     if (encoding == nil) {
433         encoding = textEncodingName;
434     }
435     [self setEncoding:encoding userChosen:userChosen];
436
437     [self addData:data];
438 }
439
440 - (id <WebCoreResourceHandle>)startLoadingResource:(id <WebCoreResourceLoader>)resourceLoader withMethod:(NSString *)method URL:(NSURL *)URL customHeaders:(NSDictionary *)customHeaders
441 {
442     // If we are no longer attached to a WebView, this must be an attempted load from an
443     // onUnload handler, so let's just block it.
444     if ([[self webFrame] webView] == nil)
445         return nil;
446
447     // Since this is a subresource, we can load any URL (we ignore the return value).
448     // But we still want to know whether we should hide the referrer or not, so we call the canLoadURL method.
449     BOOL hideReferrer;
450     [self canLoadURL:URL fromReferrer:[self referrer] hideReferrer:&hideReferrer];
451
452     return [WebSubresourceLoader startLoadingResource:resourceLoader
453                                            withMethod:method
454                                                   URL:URL
455                                         customHeaders:customHeaders
456                                              referrer:(hideReferrer ? nil : [self referrer])
457                                         forDataSource:[self dataSource]];
458 }
459
460 - (id <WebCoreResourceHandle>)startLoadingResource:(id <WebCoreResourceLoader>)resourceLoader withMethod:(NSString *)method URL:(NSURL *)URL customHeaders:(NSDictionary *)customHeaders postData:(NSArray *)postData
461 {
462     // If we are no longer attached to a WebView, this must be an attempted load from an
463     // onUnload handler, so let's just block it.
464     if ([[self webFrame] webView] == nil)
465         return nil;
466
467     // Since this is a subresource, we can load any URL (we ignore the return value).
468     // But we still want to know whether we should hide the referrer or not, so we call the canLoadURL method.
469     BOOL hideReferrer;
470     [self canLoadURL:URL fromReferrer:[self referrer] hideReferrer:&hideReferrer];
471
472     return [WebSubresourceLoader startLoadingResource:resourceLoader
473                                            withMethod:method 
474                                                   URL:URL
475                                         customHeaders:customHeaders
476                                              postData:postData
477                                              referrer:(hideReferrer ? nil : [self referrer])
478                                         forDataSource:[self dataSource]];
479 }
480
481 - (void)objectLoadedFromCacheWithURL:(NSURL *)URL response:(NSURLResponse *)response data:(NSData *)data
482 {
483     // FIXME: If the WebKit client changes or cancels the request, WebCore does not respect this and continues the load.
484     NSError *error;
485     id identifier;
486     NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL];
487     [_frame _requestFromDelegateForRequest:request identifier:&identifier error:&error];    
488     [_frame _saveResourceAndSendRemainingDelegateMessagesWithRequest:request identifier:identifier response:response data:data error:error];
489     [request release];
490 }
491
492 - (NSData *)syncLoadResourceWithMethod:(NSString *)method URL:(NSURL *)URL customHeaders:(NSDictionary *)requestHeaders postData:(NSArray *)postData finalURL:(NSURL **)finalURL responseHeaders:(NSDictionary **)responseHeaderDict statusCode:(int *)statusCode
493 {
494     // Since this is a subresource, we can load any URL (we ignore the return value).
495     // But we still want to know whether we should hide the referrer or not, so we call the canLoadURL method.
496     BOOL hideReferrer;
497     [self canLoadURL:URL fromReferrer:[self referrer] hideReferrer:&hideReferrer];
498
499     NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL];
500     [request setTimeoutInterval:10];
501
502     // setHTTPMethod is not called for GET requests to work around <rdar://4464032>.
503     if (![method isEqualToString:@"GET"])
504         [request setHTTPMethod:method];
505
506     if (postData)        
507         webSetHTTPBody(request, postData);
508
509     NSEnumerator *e = [requestHeaders keyEnumerator];
510     NSString *key;
511     while ((key = (NSString *)[e nextObject]) != nil) {
512         [request addValue:[requestHeaders objectForKey:key] forHTTPHeaderField:key];
513     }
514     
515     [request setCachePolicy:[[[self dataSource] request] cachePolicy]];
516     if (!hideReferrer)
517         [request _web_setHTTPReferrer:[self referrer]];
518     
519     WebView *webView = [self webView];
520     [request setMainDocumentURL:[[[[webView mainFrame] dataSource] request] URL]];
521     [request _web_setHTTPUserAgent:[webView userAgentForURL:[request URL]]];
522     
523     NSError *error = nil;
524     id identifier = nil;    
525     NSURLRequest *newRequest = [_frame _requestFromDelegateForRequest:request identifier:&identifier error:&error];
526     
527     NSURLResponse *response = nil;
528     NSData *result = nil;
529     if (error == nil) {
530         ASSERT(newRequest != nil);
531         result = [NSURLConnection sendSynchronousRequest:newRequest returningResponse:&response error:&error];
532     }
533     
534     if (error == nil) {
535         *finalURL = [response URL];
536         if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
537             NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; 
538             *responseHeaderDict = [httpResponse allHeaderFields];
539             *statusCode = [httpResponse statusCode];
540         } else {
541             *responseHeaderDict = [NSDictionary dictionary];
542             *statusCode = 200;
543         }
544     } else {
545         *finalURL = URL;
546         *responseHeaderDict = [NSDictionary dictionary];
547         if ([error domain] == NSURLErrorDomain) {
548             *statusCode = [error code];
549         } else {
550             *statusCode = 404;
551         }
552     }
553     
554     [_frame _saveResourceAndSendRemainingDelegateMessagesWithRequest:newRequest identifier:identifier response:response data:result error:error];
555     [request release];
556     
557     return result;
558 }
559
560 - (BOOL)isReloading
561 {
562     return [[[self dataSource] request] cachePolicy] == NSURLRequestReloadIgnoringCacheData;
563 }
564
565 // We would like a better value for a maximum time_t,
566 // but there is no way to do that in C with any certainty.
567 // INT_MAX should work well enough for our purposes.
568 #define MAX_TIME_T ((time_t)INT_MAX)    
569
570 - (time_t)expiresTimeForResponse:(NSURLResponse *)response
571 {
572     // This check can be removed when the new Foundation method
573     // has been around long enough for everyone to have it.
574     ASSERT([response respondsToSelector:@selector(_calculatedExpiration)]);
575
576     NSTimeInterval expiration = [response _calculatedExpiration];
577     expiration += kCFAbsoluteTimeIntervalSince1970;
578     return expiration > MAX_TIME_T ? MAX_TIME_T : expiration;
579 }
580
581 - (void)reportClientRedirectToURL:(NSURL *)URL delay:(NSTimeInterval)seconds fireDate:(NSDate *)date lockHistory:(BOOL)lockHistory isJavaScriptFormAction:(BOOL)isJavaScriptFormAction
582 {
583     [_frame _clientRedirectedTo:URL delay:seconds fireDate:date lockHistory:lockHistory isJavaScriptFormAction:(BOOL)isJavaScriptFormAction];
584 }
585
586 - (void)reportClientRedirectCancelled:(BOOL)cancelWithLoadInProgress
587 {
588     [_frame _clientRedirectCancelledOrFinished:cancelWithLoadInProgress];
589 }
590
591 - (void)close
592 {
593     [_frame release];
594     _frame = nil;
595 }
596
597 - (void)focusWindow
598 {
599     [[[self webView] _UIDelegateForwarder] webViewFocus:[self webView]];
600 }
601
602 - (void)unfocusWindow
603 {
604     if ([[self window] isKeyWindow] || [[[self window] attachedSheet] isKeyWindow]) {
605         [NSApp _cycleWindowsReversed:FALSE];
606     }
607 }
608
609 - (void)formControlIsBecomingFirstResponder:(NSView *)formControl
610 {
611     // When a form element becomes first responder, its enclosing WebHTMLView might need to
612     // change its focus-displaying state, but isn't otherwise notified.
613     [(WebHTMLView *)[[_frame frameView] documentView] _formControlIsBecomingFirstResponder:formControl];
614 }
615
616 - (void)formControlIsResigningFirstResponder:(NSView *)formControl
617 {
618     // When a form element resigns first responder, its enclosing WebHTMLView might need to
619     // change its focus-displaying state, but isn't otherwise notified.
620     [(WebHTMLView *)[[_frame frameView] documentView] _formControlIsResigningFirstResponder:formControl];
621 }
622
623 - (void)setIconURL:(NSURL *)URL
624 {
625     [[self dataSource] _setIconURL:URL];
626 }
627
628 - (void)setIconURL:(NSURL *)URL withType:(NSString *)type
629 {
630     [[self dataSource] _setIconURL:URL withType:type];
631 }
632
633 - (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
634 {
635     BOOL hideReferrer;
636     if (![self canLoadURL:URL fromReferrer:referrer hideReferrer:&hideReferrer])
637         return;
638
639     if ([target length] == 0) {
640         target = nil;
641     }
642
643     WebFrame *targetFrame = [_frame findFrameNamed:target];
644     if (![self canTargetLoadInFrame:[targetFrame _bridge]]) {
645         return;
646     }
647     
648     WebFrameLoadType loadType;
649     
650     if (reload)
651         loadType = WebFrameLoadTypeReload;
652     else if (!forUser)
653         loadType = WebFrameLoadTypeInternal;
654     else
655         loadType = WebFrameLoadTypeStandard;
656     [_frame _loadURL:URL referrer:(hideReferrer ? nil : referrer) loadType:loadType target:target triggeringEvent:event form:form formValues:values];
657
658     if (targetFrame != nil && _frame != targetFrame) {
659         [[targetFrame _bridge] focusWindow];
660     }
661 }
662
663 - (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
664 {
665     BOOL hideReferrer;
666     if (![self canLoadURL:URL fromReferrer:referrer hideReferrer:&hideReferrer])
667         return;
668
669     if ([target length] == 0) {
670         target = nil;
671     }
672
673     WebFrame *targetFrame = [_frame findFrameNamed:target];
674     if (![self canTargetLoadInFrame:[targetFrame _bridge]]) {
675         return;
676     }
677
678     [_frame _postWithURL:URL referrer:(hideReferrer ? nil : referrer) target:target data:postData contentType:contentType triggeringEvent:event form:form formValues:values];
679
680     if (targetFrame != nil && _frame != targetFrame) {
681         [[targetFrame _bridge] focusWindow];
682     }
683 }
684
685 - (WebCoreFrameBridge *)createChildFrameNamed:(NSString *)frameName 
686                                       withURL:(NSURL *)URL
687                                      referrer:(NSString *)referrer
688                                    renderPart:(WebCoreRenderPart *)childRenderPart
689                               allowsScrolling:(BOOL)allowsScrolling 
690                                   marginWidth:(int)width
691                                  marginHeight:(int)height
692 {
693     BOOL hideReferrer;
694     if (![self canLoadURL:URL fromReferrer:referrer hideReferrer:&hideReferrer])
695         return nil;
696
697     ASSERT(_frame);
698     
699     WebFrameView *childView = [[WebFrameView alloc] initWithFrame:NSMakeRect(0,0,0,0)];
700     [childView setAllowsScrolling:allowsScrolling];
701     WebFrameBridge *newBridge = [[WebFrameBridge alloc] initSubframeWithRenderer:childRenderPart frameName:frameName view:childView];
702     [_frame _addChild:[newBridge webFrame]];
703     [childView release];
704
705     [childView _setMarginWidth:width];
706     [childView _setMarginHeight:height];
707
708     [newBridge release];
709
710     if (!newBridge)
711         return nil;
712
713     [_frame _loadURL:URL referrer:(hideReferrer ? nil : referrer) intoChild:[newBridge webFrame]];
714
715     return newBridge;
716 }
717
718 - (void)saveDocumentState:(NSArray *)documentState
719 {
720     WebHistoryItem *item = [_frame _itemForSavingDocState];
721     LOG(Loading, "%@: saving form state from to 0x%x", [_frame name], item);
722     if (item) {
723         [item setDocumentState:documentState];
724         // You might think we could save the scroll state here too, but unfortunately this
725         // often gets called after WebFrame::_transitionToCommitted has restored the scroll
726         // position of the next document.
727     }
728 }
729
730 - (NSArray *)documentState
731 {
732     LOG(Loading, "%@: restoring form state from item 0x%x", [_frame name], [_frame _itemForRestoringDocState]);
733     return [[_frame _itemForRestoringDocState] documentState];
734 }
735
736 - (BOOL)saveDocumentToPageCache:(id)documentInfo
737 {
738     WebHistoryItem *item = [_frame _itemForSavingDocState];
739     if (![item hasPageCache]) {
740         return false;
741     }
742     [[item pageCache] setObject:documentInfo forKey:WebCorePageCacheStateKey];
743     return true;
744 }
745
746 - (NSString *)userAgentForURL:(NSURL *)URL
747 {
748     return [[self webView] userAgentForURL:URL];
749 }
750
751 - (BOOL)inNextKeyViewOutsideWebFrameViews
752 {
753     return _inNextKeyViewOutsideWebFrameViews;
754 }
755
756 - (NSView *)_nextKeyViewOutsideWebFrameViewsWithValidityCheck:(BOOL)mustBeValid
757 {
758     // We can get here in unusual situations such as the one listed in 4451831, so we
759     // return nil to avoid an infinite recursion.
760     if (_inNextKeyViewOutsideWebFrameViews)
761         return nil;
762     
763     _inNextKeyViewOutsideWebFrameViews = YES;
764     WebView *webView = [self webView];
765     // Do not ask webView for its next key view, but rather, ask it for 
766     // the next key view of the last view in its key view loop.
767     // Doing so gives us the correct answer as calculated by AppKit, 
768     // and makes HTML views behave like other views.
769     NSView *lastViewInLoop = [webView _findLastViewInKeyViewLoop];
770     NSView *nextKeyView = mustBeValid ? [lastViewInLoop nextValidKeyView] : [lastViewInLoop nextKeyView];
771     _inNextKeyViewOutsideWebFrameViews = NO;
772     return nextKeyView;
773 }
774
775 - (NSView *)nextKeyViewOutsideWebFrameViews
776 {
777     return [self _nextKeyViewOutsideWebFrameViewsWithValidityCheck:NO];
778 }
779
780 - (NSView *)nextValidKeyViewOutsideWebFrameViews
781 {
782     return [self _nextKeyViewOutsideWebFrameViewsWithValidityCheck:YES];
783 }
784
785 - (NSView *)previousKeyViewOutsideWebFrameViews
786 {
787     WebView *webView = [self webView];
788     NSView *previousKeyView = [webView previousKeyView];
789     return previousKeyView;
790 }
791
792 - (BOOL)defersLoading
793 {
794     return [[self webView] defersCallbacks];
795 }
796
797 - (void)setDefersLoading:(BOOL)defers
798 {
799     [[self webView] setDefersCallbacks:defers];
800 }
801
802 - (void)setNeedsReapplyStyles
803 {
804     NSView <WebDocumentView> *view = [[_frame frameView] documentView];
805     if ([view isKindOfClass:[WebHTMLView class]]) {
806         [(WebHTMLView *)view setNeedsToApplyStyles:YES];
807         [view setNeedsLayout:YES];
808         [view setNeedsDisplay:YES];
809     }
810 }
811
812 - (void)tokenizerProcessedData
813 {
814     [_frame _checkLoadComplete];
815 }
816
817 - (NSString *)incomingReferrer
818 {
819     return [[[self dataSource] request] _web_HTTPReferrer];
820 }
821
822 - (NSView *)pluginViewWithPackage:(WebPluginPackage *)pluginPackage
823                    attributeNames:(NSArray *)attributeNames
824                   attributeValues:(NSArray *)attributeValues
825                           baseURL:(NSURL *)baseURL
826 {
827     WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
828     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
829         
830     WebPluginController *pluginController = [docView _pluginController];
831     
832     // Store attributes in a dictionary so they can be passed to WebPlugins.
833     NSMutableDictionary *attributes = [[NSMutableDictionary alloc] initWithObjects:attributeValues forKeys:attributeNames];
834     
835     [pluginPackage load];
836     Class viewFactory = [pluginPackage viewFactory];
837     
838     NSView *view = nil;
839     NSDictionary *arguments = nil;
840     
841     if ([viewFactory respondsToSelector:@selector(plugInViewWithArguments:)]) {
842         arguments = [NSDictionary dictionaryWithObjectsAndKeys:
843             baseURL, WebPlugInBaseURLKey,
844             attributes, WebPlugInAttributesKey,
845             pluginController, WebPlugInContainerKey,
846             [NSNumber numberWithInt:WebPlugInModeEmbed], WebPlugInModeKey,
847             nil];
848         LOG(Plugins, "arguments:\n%@", arguments);
849     } else if ([viewFactory respondsToSelector:@selector(pluginViewWithArguments:)]) {
850         arguments = [NSDictionary dictionaryWithObjectsAndKeys:
851             baseURL, WebPluginBaseURLKey,
852             attributes, WebPluginAttributesKey,
853             pluginController, WebPluginContainerKey,
854             nil];
855         LOG(Plugins, "arguments:\n%@", arguments);
856     }
857
858     view = [WebPluginController plugInViewWithArguments:arguments fromPluginPackage:pluginPackage];
859     
860     [attributes release];
861     return view;
862 }
863
864 - (NSString *)valueForKey:(NSString *)key keys:(NSArray *)keys values:(NSArray *)values
865 {
866     unsigned count = [keys count];
867     unsigned i;
868     for (i = 0; i < count; i++) {
869         if ([[keys objectAtIndex:i] _webkit_isCaseInsensitiveEqualToString:key])
870             return [values objectAtIndex:i];
871     }
872     return nil;
873 }
874
875 - (NSView *)viewForPluginWithURL:(NSURL *)URL
876                   attributeNames:(NSArray *)attributeNames
877                  attributeValues:(NSArray *)attributeValues
878                         MIMEType:(NSString *)MIMEType
879 {
880     BOOL hideReferrer;
881     if (![self canLoadURL:URL fromReferrer:[self referrer] hideReferrer:&hideReferrer])
882         return nil;
883
884     ASSERT([attributeNames count] == [attributeValues count]);
885
886     WebBasePluginPackage *pluginPackage = nil;
887     NSView *view = nil;
888     int errorCode = 0;
889
890     WebView *wv = [self webView];
891     id wd = [wv UIDelegate];
892
893     if ([wd respondsToSelector:@selector(webView:plugInViewWithArguments:)]) {
894         NSMutableDictionary *attributes = [[NSMutableDictionary alloc] initWithObjects:attributeValues forKeys:attributeNames];
895         NSDictionary *arguments = [NSDictionary dictionaryWithObjectsAndKeys:
896             attributes, WebPlugInAttributesKey,
897             [NSNumber numberWithInt:WebPlugInModeEmbed], WebPlugInModeKey,
898             URL, WebPlugInBaseURLKey, // URL might be nil, so add it last
899             nil];
900         [attributes release];
901         view = [wd webView:wv plugInViewWithArguments:arguments];
902         if (view)
903             return view;
904     }
905
906     if ([MIMEType length] != 0)
907         pluginPackage = [[WebPluginDatabase installedPlugins] pluginForMIMEType:MIMEType];
908     else
909         MIMEType = nil;
910     
911     NSString *extension = [[URL path] pathExtension];
912     if (!pluginPackage && [extension length] != 0) {
913         pluginPackage = [[WebPluginDatabase installedPlugins] pluginForExtension:extension];
914         if (pluginPackage) {
915             NSString *newMIMEType = [pluginPackage MIMETypeForExtension:extension];
916             if ([newMIMEType length] != 0)
917                 MIMEType = newMIMEType;
918         }
919     }
920
921     NSURL *baseURL = [self baseURL];
922     if (pluginPackage) {
923         if ([pluginPackage isKindOfClass:[WebPluginPackage class]]) {
924             view = [self pluginViewWithPackage:(WebPluginPackage *)pluginPackage
925                                 attributeNames:attributeNames
926                                attributeValues:attributeValues
927                                        baseURL:baseURL];
928         } else if ([pluginPackage isKindOfClass:[WebNetscapePluginPackage class]]) {
929             WebNetscapePluginEmbeddedView *embeddedView = [[[WebNetscapePluginEmbeddedView alloc] initWithFrame:NSZeroRect
930                                                                   plugin:(WebNetscapePluginPackage *)pluginPackage
931                                                                      URL:URL
932                                                                  baseURL:baseURL
933                                                                 MIMEType:MIMEType
934                                                            attributeKeys:attributeNames
935                                                          attributeValues:attributeValues] autorelease];
936             view = embeddedView;
937             [embeddedView setWebFrame:_frame];
938         } else
939             ASSERT_NOT_REACHED();
940     } else
941         errorCode = WebKitErrorCannotFindPlugIn;
942
943     if (!errorCode && !view)
944         errorCode = WebKitErrorCannotLoadPlugIn;
945
946     if (errorCode) {
947         NSString *pluginPage = [self valueForKey:@"pluginspage" keys:attributeNames values:attributeValues];
948         NSURL *pluginPageURL = pluginPage != nil ? [self URLWithAttributeString:pluginPage] : nil;
949         NSError *error = [[NSError alloc] _initWithPluginErrorCode:errorCode
950                                                         contentURL:URL
951                                                      pluginPageURL:pluginPageURL
952                                                         pluginName:[pluginPackage name]
953                                                           MIMEType:MIMEType];
954         WebNullPluginView *nullView = [[[WebNullPluginView alloc] initWithFrame:NSZeroRect error:error] autorelease];
955         [nullView setWebFrame:_frame];
956         view = nullView;
957         [error release];
958     }
959     
960     ASSERT(view);
961     return view;
962 }
963
964 - (NSView *)viewForJavaAppletWithFrame:(NSRect)theFrame
965                         attributeNames:(NSArray *)attributeNames
966                        attributeValues:(NSArray *)attributeValues
967                                baseURL:(NSURL *)baseURL;
968 {
969     NSString *MIMEType = @"application/x-java-applet";
970     WebBasePluginPackage *pluginPackage;
971     NSView *view = nil;
972     
973     pluginPackage = [[WebPluginDatabase installedPlugins] pluginForMIMEType:MIMEType];
974
975     if (pluginPackage) {
976         if ([pluginPackage isKindOfClass:[WebPluginPackage class]]) {
977             // For some reason, the Java plug-in requires that we pass the dimension of the plug-in as attributes.
978             NSMutableArray *names = [attributeNames mutableCopy];
979             NSMutableArray *values = [attributeValues mutableCopy];
980             if ([self valueForKey:@"width" keys:attributeNames values:attributeValues] == nil) {
981                 [names addObject:@"width"];
982                 [values addObject:[NSString stringWithFormat:@"%d", (int)theFrame.size.width]];
983             }
984             if ([self valueForKey:@"height" keys:attributeNames values:attributeValues] == nil) {
985                 [names addObject:@"height"];
986                 [values addObject:[NSString stringWithFormat:@"%d", (int)theFrame.size.height]];
987             }
988             view = [self pluginViewWithPackage:(WebPluginPackage *)pluginPackage
989                                 attributeNames:names
990                                attributeValues:values
991                                        baseURL:baseURL];
992             [names release];
993             [values release];
994         } else if ([pluginPackage isKindOfClass:[WebNetscapePluginPackage class]]) {
995             view = [[[WebNetscapePluginEmbeddedView alloc] initWithFrame:theFrame
996                                                                   plugin:(WebNetscapePluginPackage *)pluginPackage
997                                                                      URL:nil
998                                                                  baseURL:baseURL
999                                                                 MIMEType:MIMEType
1000                                                            attributeKeys:attributeNames
1001                                                          attributeValues:attributeValues] autorelease];
1002         } else {
1003             ASSERT_NOT_REACHED();
1004         }
1005     }
1006
1007     if (!view) {
1008         NSError *error = [[NSError alloc] _initWithPluginErrorCode:WebKitErrorJavaUnavailable
1009                                                         contentURL:nil
1010                                                      pluginPageURL:nil
1011                                                         pluginName:[pluginPackage name]
1012                                                           MIMEType:MIMEType];
1013         view = [[[WebNullPluginView alloc] initWithFrame:theFrame error:error] autorelease];
1014         [error release];
1015     }
1016
1017     ASSERT(view);
1018
1019     return view;
1020 }
1021
1022 #ifndef NDEBUG
1023 static BOOL loggedObjectCacheSize = NO;
1024 #endif
1025
1026 - (WebPreferences *)_preferences
1027 {
1028     return [[self webView] preferences];
1029 }
1030
1031 -(int)getObjectCacheSize
1032 {
1033     vm_size_t memSize = WebSystemMainMemory();
1034     int cacheSize = [[self _preferences] _objectCacheSize];
1035     int multiplier = 1;
1036     if (memSize >= 1024 * 1024 * 1024)
1037         multiplier = 4;
1038     else if (memSize >= 512 * 1024 * 1024)
1039         multiplier = 2;
1040
1041 #ifndef NDEBUG
1042     if (!loggedObjectCacheSize){
1043         LOG (CacheSizes, "Object cache size set to %d bytes.", cacheSize * multiplier);
1044         loggedObjectCacheSize = YES;
1045     }
1046 #endif
1047
1048     return cacheSize * multiplier;
1049 }
1050
1051 - (ObjectElementType)determineObjectFromMIMEType:(NSString*)MIMEType URL:(NSURL*)URL
1052 {
1053     if ([MIMEType length] == 0) {
1054         // Try to guess the MIME type based off the extension.
1055         NSString *extension = [[URL path] pathExtension];
1056         if ([extension length] > 0) {
1057             MIMEType = WKGetMIMETypeForExtension(extension);
1058             if ([MIMEType length] == 0 && [[WebPluginDatabase installedPlugins] pluginForExtension:extension])
1059                 // If no MIME type is specified, use a plug-in if we have one that can handle the extension.
1060                 return ObjectElementPlugin;
1061         }
1062     }
1063
1064     if ([MIMEType length] == 0)
1065         return ObjectElementFrame; // Go ahead and hope that we can display the content.
1066                 
1067     Class viewClass = [WebFrameView _viewClassForMIMEType:MIMEType];
1068     if (!viewClass) {
1069         // No view class is registered to handle this MIME type.  Check to see if there is a plugin which can handle this MIME type.
1070         // This check is required because the Java plugin does not register an NSView class, so that Java files are downloaded when 
1071         // not embedded.
1072         if ([[WebPluginDatabase installedPlugins] pluginForMIMEType:MIMEType])
1073             return ObjectElementPlugin;
1074         else
1075             return ObjectElementNone;
1076     }
1077     
1078     if ([viewClass isSubclassOfClass:[WebImageView class]])
1079         return ObjectElementImage;
1080     
1081     // If we're a supported type other than a plugin, we want to make a frame.
1082     // Ultimately we should just use frames for all mime types (plugins and HTML/XML/text documents),
1083     // but for now we're burdened with making a distinction between the two.
1084     if ([viewClass isSubclassOfClass:[WebNetscapePluginDocumentView class]] || [viewClass isSubclassOfClass:[WebPluginDocumentView class]])
1085         return ObjectElementPlugin;
1086     return ObjectElementFrame;
1087 }
1088
1089 - (void)loadEmptyDocumentSynchronously
1090 {
1091     NSURL *url = [[NSURL alloc] initWithString:@""];
1092     NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
1093     [_frame loadRequest:request];
1094     [request release];
1095     [url release];
1096 }
1097
1098 - (NSString *)MIMETypeForPath:(NSString *)path
1099 {
1100     ASSERT(path);
1101     NSString *extension = [path pathExtension];
1102     NSString *type = WKGetMIMETypeForExtension(extension);
1103     return [type length] == 0 ? (NSString *)@"application/octet-stream" : type;
1104 }
1105
1106 - (void)allowDHTMLDrag:(BOOL *)flagDHTML UADrag:(BOOL *)flagUA
1107 {
1108     WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
1109     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
1110     unsigned int mask = [docView _delegateDragSourceActionMask];
1111     *flagDHTML = (mask & WebDragSourceActionDHTML) != 0;
1112     *flagUA = ((mask & WebDragSourceActionImage) || (mask & WebDragSourceActionLink) || (mask & WebDragSourceActionSelection));
1113 }
1114
1115 - (BOOL)startDraggingImage:(NSImage *)dragImage at:(NSPoint)dragLoc operation:(NSDragOperation)op event:(NSEvent *)event sourceIsDHTML:(BOOL)flag DHTMLWroteData:(BOOL)dhtmlWroteData
1116 {
1117     WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
1118     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
1119     return [docView _startDraggingImage:dragImage at:dragLoc operation:op event:event sourceIsDHTML:flag DHTMLWroteData:dhtmlWroteData];
1120 }
1121
1122 - (void)handleAutoscrollForMouseDragged:(NSEvent *)event;
1123 {
1124     WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
1125
1126     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
1127
1128     [docView _handleAutoscrollForMouseDragged:event];
1129 }
1130
1131 - (BOOL)mayStartDragAtEventLocation:(NSPoint)location
1132 {
1133     WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
1134
1135     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
1136
1137     return [docView _mayStartDragAtEventLocation:location];
1138 }
1139
1140 - (BOOL)selectWordBeforeMenuEvent
1141 {
1142     return [[self webView] _selectWordBeforeMenuEvent];
1143 }
1144
1145 - (int)historyLength
1146 {
1147     return [[[self webView] backForwardList] backListCount] + 1;
1148 }
1149
1150 - (BOOL)canGoBackOrForward:(int)distance
1151 {
1152     if (distance == 0)
1153         return TRUE;
1154
1155     if (distance > 0 && distance <= [[[self webView] backForwardList] forwardListCount])
1156         return TRUE;
1157
1158     if (distance < 0 && -distance <= [[[self webView] backForwardList] backListCount])
1159         return TRUE;
1160     
1161     return FALSE;
1162 }
1163
1164 - (void)goBackOrForward:(int)distance
1165 {
1166     if (distance == 0) {
1167         return;
1168     }
1169     WebView *webView = [self webView];
1170     WebBackForwardList *list = [webView backForwardList];
1171     WebHistoryItem *item = [list itemAtIndex:distance];
1172     if (!item) {
1173         if (distance > 0) {
1174             int forwardListCount = [list forwardListCount];
1175             if (forwardListCount > 0) {
1176                 item = [list itemAtIndex:forwardListCount];
1177             }
1178         } else {
1179             int backListCount = [list forwardListCount];
1180             if (backListCount > 0) {
1181                 item = [list itemAtIndex:-backListCount];
1182             }
1183         }
1184     }
1185     if (item) {
1186         [webView goToBackForwardItem:item];
1187     }
1188 }
1189
1190 static id <WebFormDelegate> formDelegate(WebFrameBridge *self)
1191 {
1192     ASSERT(self->_frame != nil);
1193     return [[self->_frame webView] _formDelegate];
1194 }
1195
1196 #define FormDelegateLog(ctrl)  LOG(FormDelegate, "control=%@", ctrl)
1197
1198 - (void)textFieldDidBeginEditing:(DOMHTMLInputElement *)element
1199 {
1200     FormDelegateLog(element);
1201     [formDelegate(self) textFieldDidBeginEditing:element inFrame:_frame];
1202 }
1203
1204 - (void)textFieldDidEndEditing:(DOMHTMLInputElement *)element
1205 {
1206     FormDelegateLog(element);
1207     [formDelegate(self) textFieldDidEndEditing:element inFrame:_frame];
1208 }
1209
1210 - (void)textDidChangeInTextField:(DOMHTMLInputElement *)element
1211 {
1212     FormDelegateLog(element);
1213     [formDelegate(self) textDidChangeInTextField:(DOMHTMLInputElement *)element inFrame:_frame];
1214 }
1215
1216 - (void)textDidChangeInTextArea:(DOMHTMLTextAreaElement *)element
1217 {
1218     FormDelegateLog(element);
1219     [formDelegate(self) textDidChangeInTextArea:element inFrame:_frame];
1220 }
1221
1222 - (BOOL)textField:(DOMHTMLInputElement *)element doCommandBySelector:(SEL)commandSelector
1223 {
1224     FormDelegateLog(element);
1225     return [formDelegate(self) textField:element doCommandBySelector:commandSelector inFrame:_frame];
1226 }
1227
1228 - (BOOL)textField:(DOMHTMLInputElement *)element shouldHandleEvent:(NSEvent *)event
1229 {
1230     FormDelegateLog(element);
1231     return [formDelegate(self) textField:element shouldHandleEvent:event inFrame:_frame];
1232 }
1233
1234 - (void)frameDetached
1235 {
1236     [_frame stopLoading];
1237     [_frame _detachFromParent];
1238 }
1239
1240 - (void)setHasBorder:(BOOL)hasBorder
1241 {
1242     [[_frame frameView] _setHasBorder:hasBorder];
1243 }
1244
1245 - (NSFileWrapper *)fileWrapperForURL:(NSURL *)URL
1246 {
1247     return [[_frame dataSource] _fileWrapperForURL:URL];
1248 }
1249
1250 - (void)print
1251 {
1252     id wd = [[self webView] UIDelegate];
1253     
1254     if ([wd respondsToSelector:@selector(webView:printFrameView:)]) {
1255         [wd webView:[self webView] printFrameView:[_frame frameView]];
1256     } else if ([wd respondsToSelector:@selector(webViewPrint:)]) {
1257         // Backward-compatible, but webViewPrint: was never public, so probably not needed.
1258         [wd webViewPrint:[self webView]];
1259     } else {
1260         [[WebDefaultUIDelegate sharedUIDelegate] webView:[self webView] printFrameView:[_frame frameView]];
1261     }
1262 }
1263
1264 - (jobject)getAppletInView:(NSView *)view
1265 {
1266     jobject applet;
1267
1268     if ([view respondsToSelector:@selector(webPlugInGetApplet)])
1269         applet = [view webPlugInGetApplet];
1270     else
1271         applet = [self pollForAppletInView:view];
1272         
1273     return applet;
1274 }
1275
1276 // NOTE: pollForAppletInView: will block until the block is ready to use, or
1277 // until a timeout is exceeded.  It will return nil if the timeour is
1278 // exceeded.
1279 // Deprecated, use getAppletInView:.
1280 - (jobject)pollForAppletInView:(NSView *)view
1281 {
1282     jobject applet = 0;
1283     
1284     if ([view respondsToSelector:@selector(pollForAppletInWindow:)]) {
1285         // The Java VM needs the containing window of the view to
1286         // initialize.  The view may not yet be in the window's view 
1287         // hierarchy, so we have to pass the window when requesting
1288         // the applet.
1289         applet = [view pollForAppletInWindow:[[self webView] window]];
1290     }
1291     
1292     return applet;
1293 }
1294
1295 - (void)respondToChangedContents
1296 {
1297     NSView <WebDocumentView> *view = [[_frame frameView] documentView];
1298     if ([view isKindOfClass:[WebHTMLView class]]) {
1299         [(WebHTMLView *)view _updateFontPanel];
1300     }
1301     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewDidChangeNotification object:[self webView]];
1302 }
1303
1304 - (void)respondToChangedSelection
1305 {
1306     NSView <WebDocumentView> *view = [[_frame frameView] documentView];
1307     if ([view isKindOfClass:[WebHTMLView class]]) {
1308         [(WebHTMLView *)view _selectionChanged];
1309     }
1310     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewDidChangeSelectionNotification object:[self webView]];
1311 }
1312
1313 - (NSUndoManager *)undoManager
1314 {
1315     return [[self webView] undoManager];
1316 }
1317
1318 - (void)issueCutCommand
1319 {
1320     [[self webView] cut:nil];
1321 }
1322
1323 - (void)issueCopyCommand
1324 {
1325     [[self webView] copy:nil];
1326 }
1327
1328 - (void)issuePasteCommand
1329 {
1330     [[self webView] paste:nil];
1331 }
1332
1333 - (void)issuePasteAndMatchStyleCommand
1334 {
1335     [[self webView] pasteAsPlainText:nil];
1336 }
1337
1338 - (void)issueTransposeCommand
1339 {
1340     NSView <WebDocumentView> *view = [[_frame frameView] documentView];
1341     if ([view isKindOfClass:[WebHTMLView class]]) {
1342         [(WebHTMLView *)view transpose:nil];
1343     }
1344 }
1345
1346 - (BOOL)canPaste
1347 {
1348     return [[self webView] _canPaste];
1349 }
1350
1351 - (void)setIsSelected:(BOOL)isSelected forView:(NSView *)view
1352 {
1353     if ([view respondsToSelector:@selector(webPlugInSetIsSelected:)]) {
1354         [view webPlugInSetIsSelected:isSelected];
1355     }
1356     else if ([view respondsToSelector:@selector(setIsSelected:)]) {
1357         [view setIsSelected:isSelected];
1358     }
1359 }
1360
1361 - (NSString *)overrideMediaType
1362 {
1363     return [[self webView] mediaStyle];
1364 }
1365
1366 - (BOOL)isEditable
1367 {
1368     return [[self webView] isEditable];
1369 }
1370
1371 - (BOOL)shouldChangeSelectedDOMRange:(DOMRange *)currentRange toDOMRange:(DOMRange *)proposedRange affinity:(NSSelectionAffinity)selectionAffinity stillSelecting:(BOOL)flag
1372 {
1373     return [[self webView] _shouldChangeSelectedDOMRange:currentRange toDOMRange:proposedRange affinity:selectionAffinity stillSelecting:flag];
1374 }
1375
1376 - (BOOL)shouldBeginEditing:(DOMRange *)range
1377 {
1378     return [[self webView] _shouldBeginEditingInDOMRange:range];
1379 }
1380
1381 - (BOOL)shouldEndEditing:(DOMRange *)range
1382 {
1383     return [[self webView] _shouldEndEditingInDOMRange:range];
1384 }
1385
1386 - (void)didBeginEditing
1387 {
1388     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewDidBeginEditingNotification object:[_frame webView]];
1389 }
1390
1391 - (void)didEndEditing
1392 {
1393     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewDidEndEditingNotification object:[_frame webView]];
1394 }
1395
1396 - (void)windowObjectCleared
1397 {
1398     WebView *wv = [self webView];
1399     [[wv _frameLoadDelegateForwarder] webView:wv windowScriptObjectAvailable:[self windowScriptObject]];
1400     if ([wv scriptDebugDelegate]) {
1401         [_frame _attachScriptDebugger];
1402     }
1403 }
1404
1405 - (int)spellCheckerDocumentTag
1406 {
1407     return [[self webView] spellCheckerDocumentTag];
1408 }
1409
1410 - (BOOL)isContinuousSpellCheckingEnabled
1411 {
1412     return [[self webView] isContinuousSpellCheckingEnabled];
1413 }
1414
1415 - (void)didFirstLayout
1416 {
1417     [_frame _didFirstLayout];
1418     WebView *wv = [self webView];
1419     [[wv _frameLoadDelegateForwarder] webView:wv didFirstLayoutInFrame:_frame];
1420 }
1421
1422 - (BOOL)_compareDashboardRegions:(NSDictionary *)regions
1423 {
1424     return [lastDashboardRegions isEqualToDictionary:regions];
1425 }
1426
1427 - (void)dashboardRegionsChanged:(NSMutableDictionary *)regions
1428 {
1429     WebView *wv = [self webView];
1430     id wd = [wv UIDelegate];
1431     
1432     [wv _addScrollerDashboardRegions:regions];
1433     
1434     if (![self _compareDashboardRegions:regions]) {
1435         if ([wd respondsToSelector:@selector(webView:dashboardRegionsChanged:)]) {
1436             [wd webView:wv dashboardRegionsChanged:regions];
1437             [lastDashboardRegions release];
1438             lastDashboardRegions = [regions retain];
1439         }
1440     }
1441 }
1442
1443 - (NSString *)nameForUndoAction:(WebUndoAction)undoAction
1444 {
1445     switch (undoAction) {
1446         case WebUndoActionUnspecified: return nil;
1447         case WebUndoActionSetColor: return UI_STRING_KEY("Set Color", "Set Color (Undo action name)", "Undo action name");
1448         case WebUndoActionSetBackgroundColor: return UI_STRING_KEY("Set Background Color", "Set Background Color (Undo action name)", "Undo action name");
1449         case WebUndoActionTurnOffKerning: return UI_STRING_KEY("Turn Off Kerning", "Turn Off Kerning (Undo action name)", "Undo action name");
1450         case WebUndoActionTightenKerning: return UI_STRING_KEY("Tighten Kerning", "Tighten Kerning (Undo action name)", "Undo action name");
1451         case WebUndoActionLoosenKerning: return UI_STRING_KEY("Loosen Kerning", "Loosen Kerning (Undo action name)", "Undo action name");
1452         case WebUndoActionUseStandardKerning: return UI_STRING_KEY("Use Standard Kerning", "Use Standard Kerning (Undo action name)", "Undo action name");
1453         case WebUndoActionTurnOffLigatures: return UI_STRING_KEY("Turn Off Ligatures", "Turn Off Ligatures (Undo action name)", "Undo action name");
1454         case WebUndoActionUseStandardLigatures: return UI_STRING_KEY("Use Standard Ligatures", "Use Standard Ligatures (Undo action name)", "Undo action name");
1455         case WebUndoActionUseAllLigatures: return UI_STRING_KEY("Use All Ligatures", "Use All Ligatures (Undo action name)", "Undo action name");
1456         case WebUndoActionRaiseBaseline: return UI_STRING_KEY("Raise Baseline", "Raise Baseline (Undo action name)", "Undo action name");
1457         case WebUndoActionLowerBaseline: return UI_STRING_KEY("Lower Baseline", "Lower Baseline (Undo action name)", "Undo action name");
1458         case WebUndoActionSetTraditionalCharacterShape: return UI_STRING_KEY("Set Traditional Character Shape", "Set Traditional Character Shape (Undo action name)", "Undo action name");
1459         case WebUndoActionSetFont: return UI_STRING_KEY("Set Font", "Set Font (Undo action name)", "Undo action name");
1460         case WebUndoActionChangeAttributes: return UI_STRING_KEY("Change Attributes", "Change Attributes (Undo action name)", "Undo action name");
1461         case WebUndoActionAlignLeft: return UI_STRING_KEY("Align Left", "Align Left (Undo action name)", "Undo action name");
1462         case WebUndoActionAlignRight: return UI_STRING_KEY("Align Right", "Align Right (Undo action name)", "Undo action name");
1463         case WebUndoActionCenter: return UI_STRING_KEY("Center", "Center (Undo action name)", "Undo action name");
1464         case WebUndoActionJustify: return UI_STRING_KEY("Justify", "Justify (Undo action name)", "Undo action name");
1465         case WebUndoActionSetWritingDirection: return UI_STRING_KEY("Set Writing Direction", "Set Writing Direction (Undo action name)", "Undo action name");
1466         case WebUndoActionSubscript: return UI_STRING_KEY("Subscript", "Subscript (Undo action name)", "Undo action name");
1467         case WebUndoActionSuperscript: return UI_STRING_KEY("Superscript", "Superscript (Undo action name)", "Undo action name");
1468         case WebUndoActionUnderline: return UI_STRING_KEY("Underline", "Underline (Undo action name)", "Undo action name");
1469         case WebUndoActionOutline: return UI_STRING_KEY("Outline", "Outline (Undo action name)", "Undo action name");
1470         case WebUndoActionUnscript: return UI_STRING_KEY("Unscript", "Unscript (Undo action name)", "Undo action name");
1471         case WebUndoActionDrag: return UI_STRING_KEY("Drag", "Drag (Undo action name)", "Undo action name");
1472         case WebUndoActionCut: return UI_STRING_KEY("Cut", "Cut (Undo action name)", "Undo action name");
1473         case WebUndoActionPaste: return UI_STRING_KEY("Paste", "Paste (Undo action name)", "Undo action name");
1474         case WebUndoActionPasteFont: return UI_STRING_KEY("Paste Font", "Paste Font (Undo action name)", "Undo action name");
1475         case WebUndoActionPasteRuler: return UI_STRING_KEY("Paste Ruler", "Paste Ruler (Undo action name)", "Undo action name");
1476         case WebUndoActionTyping: return UI_STRING_KEY("Typing", "Typing (Undo action name)", "Undo action name");
1477         case WebUndoActionCreateLink: return UI_STRING_KEY("Create Link", "Create Link (Undo action name)", "Undo action name");
1478         case WebUndoActionUnlink: return UI_STRING_KEY("Unlink", "Unlink (Undo action name)", "Undo action name");
1479     }
1480     return nil;
1481 }
1482
1483 - (WebCorePageBridge *)createModalDialogWithURL:(NSURL *)URL
1484 {
1485     ASSERT(_frame != nil);
1486
1487     NSMutableURLRequest *request = nil;
1488
1489     if (URL != nil && ![URL _web_isEmpty]) {
1490         request = [NSMutableURLRequest requestWithURL:URL];
1491         [request _web_setHTTPReferrer:[self referrer]];
1492     }
1493
1494     WebView *currentWebView = [self webView];
1495     id UIDelegate = [currentWebView UIDelegate];
1496
1497     WebView *newWebView = nil;
1498     if ([UIDelegate respondsToSelector:@selector(webView:createWebViewModalDialogWithRequest:)])
1499         newWebView = [UIDelegate webView:currentWebView createWebViewModalDialogWithRequest:request];
1500     else if ([UIDelegate respondsToSelector:@selector(webView:createWebViewWithRequest:)])
1501         newWebView = [UIDelegate webView:currentWebView createWebViewWithRequest:request];
1502     else
1503         newWebView = [[WebDefaultUIDelegate sharedUIDelegate] webView:currentWebView createWebViewWithRequest:request];
1504
1505     return [newWebView _pageBridge];
1506 }
1507
1508 - (BOOL)canRunModal
1509 {
1510     WebView *webView = [self webView];
1511     id UIDelegate = [webView UIDelegate];
1512     return [UIDelegate respondsToSelector:@selector(webViewRunModal:)];
1513 }
1514
1515 - (BOOL)canRunModalNow
1516 {
1517     return [self canRunModal] && ![WebLoader inConnectionCallback];
1518 }
1519
1520 - (void)runModal
1521 {
1522     if (![self canRunModal])
1523         return;
1524
1525     WebView *webView = [self webView];
1526     if ([webView defersCallbacks]) {
1527         LOG_ERROR("tried to run modal in a view when it was deferring callbacks -- should never happen");
1528         return;
1529     }
1530
1531     // Defer callbacks in all the other views in this group, so we don't try to run JavaScript
1532     // in a way that could interact with this view.
1533     NSMutableArray *deferredWebViews = [NSMutableArray array];
1534     NSString *namespace = [webView groupName];
1535     if (namespace) {
1536         NSEnumerator *enumerator = [WebCoreFrameNamespaces framesInNamespace:namespace];
1537         WebView *otherWebView;
1538         while ((otherWebView = [[enumerator nextObject] webView]) != nil) {
1539             if (otherWebView != webView && ![otherWebView defersCallbacks]) {
1540                 [otherWebView setDefersCallbacks:YES];
1541                 [deferredWebViews addObject:otherWebView];
1542             }
1543         }
1544     }
1545
1546     // Go run the modal event loop.
1547     [[webView UIDelegate] webViewRunModal:webView];
1548
1549     // Restore the callbacks for any views that we deferred them for.
1550     unsigned count = [deferredWebViews count];
1551     unsigned i;
1552     for (i = 0; i < count; ++i) {
1553         WebView *otherWebView = [deferredWebViews objectAtIndex:i];
1554         [otherWebView setDefersCallbacks:NO];
1555     }
1556 }
1557
1558 - (void)handledOnloadEvents
1559 {
1560     [_frame _handledOnloadEvents];
1561 }
1562
1563 @end