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