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