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