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