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