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