WebCore:
[WebKit-https.git] / WebKit / WebCoreSupport.subproj / WebBridge.m
1 /*      
2     WebBridge.m
3     Copyright (c) 2002, 2003, Apple Computer, Inc. All rights reserved.
4 */
5
6 #import <WebKit/WebBridge.h>
7
8 #import <WebKit/WebAssertions.h>
9 #import <WebKit/WebBackForwardList.h>
10 #import <WebKit/WebBaseNetscapePluginView.h>
11 #import <WebKit/WebBasePluginPackage.h>
12 #import <WebKit/WebBaseResourceHandleDelegate.h>
13 #import <WebKit/WebDataSourcePrivate.h>
14 #import <WebKit/WebDefaultUIDelegate.h>
15 #import <WebKit/WebEditingDelegate.h>
16 #import <WebKit/WebFileButton.h>
17 #import <WebKit/WebFormDelegate.h>
18 #import <WebKit/WebFrameInternal.h>
19 #import <WebKit/WebFrameLoadDelegate.h>
20 #import <WebKit/WebFrameViewInternal.h>
21 #import <WebKit/WebHistoryItemPrivate.h>
22 #import <WebKit/WebHTMLRepresentationPrivate.h>
23 #import <WebKit/WebHTMLViewInternal.h>
24 #import <WebKit/WebJavaPlugIn.h>
25 #import <WebKit/WebJavaScriptTextInputPanel.h>
26 #import <WebKit/WebKitErrorsPrivate.h>
27 #import <WebKit/WebKitLogging.h>
28 #import <WebKit/WebKitStatisticsPrivate.h>
29 #import <WebKit/WebKitSystemBits.h>
30 #import <WebKit/WebNetscapePluginEmbeddedView.h>
31 #import <WebKit/WebNetscapePluginPackage.h>
32 #import <WebKit/WebNSObjectExtras.h>
33 #import <WebKit/WebNSURLExtras.h>
34 #import <WebKit/WebNullPluginView.h>
35 #import <WebKit/WebPlugin.h>
36 #import <WebKit/WebPluginController.h>
37 #import <WebKit/WebPluginDatabase.h>
38 #import <WebKit/WebPluginDocumentView.h>
39 #import <WebKit/WebPluginPackage.h>
40 #import <WebKit/WebPluginViewFactoryPrivate.h>
41 #import <WebKit/WebNetscapePluginDocumentView.h>
42 #import <WebKit/WebPreferencesPrivate.h>
43 #import <WebKit/WebResource.h>
44 #import <WebKit/WebSubresourceClient.h>
45 #import <WebKit/WebViewInternal.h>
46 #import <WebKit/WebViewPrivate.h>
47 #import <WebKit/WebUIDelegatePrivate.h>
48
49 #import <Foundation/NSURLRequest.h>
50 #import <Foundation/NSURLRequestPrivate.h>
51 #import <Foundation/NSString_NSURLExtras.h>
52 #import <Foundation/NSDictionary_NSURLExtras.h>
53 #import <Foundation/NSURLConnection.h>
54 #import <Foundation/NSURLResponse.h>
55 #import <Foundation/NSURLResponsePrivate.h>
56 #import <Foundation/NSURLFileTypeMappings.h>
57
58 #import <WebKit/WebLocalizableStrings.h>
59
60 #import <JavaVM/jni.h>
61
62 #define KeyboardUIModeDidChangeNotification @"com.apple.KeyboardUIModeDidChange"
63 #define AppleKeyboardUIMode CFSTR("AppleKeyboardUIMode")
64 #define UniversalAccessDomain CFSTR("com.apple.universalaccess")
65
66 // For compatibility only with old SPI. 
67 @interface NSObject (OldWebPlugin)
68 - (void)setIsSelected:(BOOL)f;
69 @end
70
71 @interface NSApplication (DeclarationStolenFromAppKit)
72 - (void)_cycleWindowsReversed:(BOOL)reversed;
73 @end
74
75 @interface NSView (AppKitSecretsWebBridgeKnowsAbout)
76 - (NSView *)_findLastViewInKeyViewLoop;
77 @end
78
79 @interface NSURLResponse (FoundationSecretsWebBridgeKnowsAbout)
80 - (NSTimeInterval)_calculatedExpiration;
81 @end
82
83 @interface NSView (JavaPluginSecrets)
84 - (jobject)pollForAppletInWindow: (NSWindow *)window;
85 @end
86
87 NSString *WebPluginBaseURLKey =     @"WebPluginBaseURL";
88 NSString *WebPluginAttributesKey =  @"WebPluginAttributes";
89 NSString *WebPluginContainerKey =   @"WebPluginContainer";
90
91 @implementation WebBridge
92
93 - (id)initWithWebFrame:(WebFrame *)webFrame
94 {
95     self = [super init];
96
97     ++WebBridgeCount;
98     
99     WebView *webView = [webFrame webView];
100     
101     // Non-retained because data source owns representation owns bridge.
102     // But WebFrame will call close on us before it goes away, which
103     // guarantees we will not have a stale reference.
104     _frame = webFrame;
105
106     [self setName:[webFrame name]];
107     [self initializeSettings:[webView _settings]];
108     [self setTextSizeMultiplier:[webView textSizeMultiplier]];
109
110     return self;
111 }
112
113 - (void)fini
114 {
115     ASSERT(_frame == nil);
116
117     if (_keyboardUIModeAccessed) {
118         [[NSDistributedNotificationCenter defaultCenter] 
119             removeObserver:self name:KeyboardUIModeDidChangeNotification object:nil];
120         [[NSNotificationCenter defaultCenter] 
121             removeObserver:self name:WebPreferencesChangedNotification object:nil];
122     }
123
124     --WebBridgeCount;
125 }
126
127 - (void)dealloc
128 {
129     [self fini];
130     [super dealloc];
131 }
132
133 - (void)finalize
134 {
135     [self fini];
136     [super finalize];
137 }
138
139 - (WebFrame *)webFrame
140 {
141     return _frame;
142 }
143
144 - (NSArray *)childFrames
145 {
146     ASSERT(_frame != nil);
147     NSArray *frames = [_frame childFrames];
148     NSEnumerator *e = [frames objectEnumerator];
149     NSMutableArray *frameBridges = [NSMutableArray arrayWithCapacity:[frames count]];
150     WebFrame *childFrame;
151     while ((childFrame = [e nextObject])) {
152         id frameBridge = [childFrame _bridge];
153         if (frameBridge)
154             [frameBridges addObject:frameBridge];
155     }
156     return frameBridges;
157 }
158
159 - (WebCoreBridge *)mainFrame
160 {
161     ASSERT(_frame != nil);
162     return [[[_frame webView] mainFrame] _bridge];
163 }
164
165 - (WebCoreBridge *)findFrameNamed:(NSString *)name;
166 {
167     ASSERT(_frame != nil);
168     return [[_frame findFrameNamed:name] _bridge];
169 }
170
171 - (NSView *)documentView
172 {
173     ASSERT(_frame != nil);
174     return [[_frame frameView] documentView];
175 }
176
177 - (WebCoreBridge *)createWindowWithURL:(NSURL *)URL frameName:(NSString *)name
178 {
179     ASSERT(_frame != nil);
180
181     NSMutableURLRequest *request = nil;
182
183     if (URL != nil && ![URL _web_isEmpty]) {
184         request = [NSMutableURLRequest requestWithURL:URL];
185         [request setHTTPReferrer:[self referrer]];
186     }
187
188     WebView *currentWebView = [_frame webView];
189     id wd = [currentWebView UIDelegate];
190     WebView *newWebView = nil;
191     
192     if ([wd respondsToSelector:@selector(webView:createWebViewWithRequest:)])
193         newWebView = [wd webView:currentWebView createWebViewWithRequest:request];
194     else
195         newWebView = [[WebDefaultUIDelegate sharedUIDelegate] webView:currentWebView createWebViewWithRequest:request];
196     [newWebView _setTopLevelFrameName:name];
197     return [[newWebView mainFrame] _bridge];
198 }
199
200 - (void)showWindow
201 {
202     WebView *wv = [_frame webView];
203     [[wv _UIDelegateForwarder] webViewShow: wv];
204 }
205
206 - (BOOL)areToolbarsVisible
207 {
208     ASSERT(_frame != nil);
209     WebView *wv = [_frame webView];
210     id wd = [wv UIDelegate];
211     if ([wd respondsToSelector: @selector(webViewAreToolbarsVisible:)])
212         return [wd webViewAreToolbarsVisible: wv];
213     return [[WebDefaultUIDelegate sharedUIDelegate] webViewAreToolbarsVisible:wv];
214 }
215
216 - (void)setToolbarsVisible:(BOOL)visible
217 {
218     ASSERT(_frame != nil);
219     WebView *wv = [_frame webView];
220     [[wv _UIDelegateForwarder] webView:wv setToolbarsVisible:visible];
221 }
222
223 - (BOOL)areScrollbarsVisible
224 {
225     ASSERT(_frame != nil);
226     return [[_frame frameView] allowsScrolling];
227 }
228
229 - (void)setScrollbarsVisible:(BOOL)visible
230 {
231     ASSERT(_frame != nil);
232     [[_frame frameView] setAllowsScrolling:visible];
233 }
234
235 - (BOOL)isStatusBarVisible
236 {
237     ASSERT(_frame != nil);
238     WebView *wv = [_frame webView];
239     id wd = [wv UIDelegate];
240     if ([wd respondsToSelector: @selector(webViewIsStatusBarVisible:)])
241         return [wd webViewIsStatusBarVisible:wv];
242     return [[WebDefaultUIDelegate sharedUIDelegate] webViewIsStatusBarVisible:wv];
243 }
244
245 - (void)setStatusBarVisible:(BOOL)visible
246 {
247     ASSERT(_frame != nil);
248     WebView *wv = [_frame webView];
249     [[wv _UIDelegateForwarder] webView:wv setStatusBarVisible:visible];
250 }
251
252 - (void)setWindowFrame:(NSRect)frameRect
253 {
254     ASSERT(_frame != nil);
255     WebView *webView = [_frame webView];
256     [[webView _UIDelegateForwarder] webView:webView setFrame:frameRect];
257 }
258
259 - (NSRect)windowFrame
260 {
261     ASSERT(_frame != nil);
262     WebView *webView = [_frame webView];
263     return [[webView _UIDelegateForwarder] webViewFrame:webView];
264 }
265
266 - (void)setWindowContentRect:(NSRect)contentRect
267 {
268     ASSERT(_frame != nil);
269     WebView *webView = [_frame webView];
270     [[webView _UIDelegateForwarder] webView:webView setFrame:contentRect];
271 }
272
273 - (NSRect)windowContentRect
274 {
275     ASSERT(_frame != nil);
276     WebView *webView = [_frame webView];
277     return [[webView _UIDelegateForwarder] webViewContentRect:webView];
278 }
279
280 - (void)setWindowIsResizable:(BOOL)resizable
281 {
282     ASSERT(_frame != nil);
283     WebView *webView = [_frame webView];
284     [[webView _UIDelegateForwarder] webView:webView setResizable:resizable];
285 }
286
287 - (BOOL)windowIsResizable
288 {
289     ASSERT(_frame != nil);
290     WebView *webView = [_frame webView];
291     return [[webView _UIDelegateForwarder] webViewIsResizable:webView];
292 }
293
294 - (NSResponder *)firstResponder
295 {
296     ASSERT(_frame != nil);
297     WebView *webView = [_frame webView];
298     return [[webView _UIDelegateForwarder] webViewFirstResponder:webView];
299 }
300
301 - (void)makeFirstResponder:(NSResponder *)view
302 {
303     ASSERT(_frame != nil);
304     WebView *webView = [_frame webView];
305     [webView _pushPerformingProgrammaticFocus];
306     [[webView _UIDelegateForwarder] webView:webView makeFirstResponder:view];
307     [webView _popPerformingProgrammaticFocus];
308 }
309
310 - (BOOL)wasFirstResponderAtMouseDownTime:(NSResponder *)responder;
311 {
312     ASSERT(_frame != nil);
313     NSView *documentView = [[_frame frameView] documentView];
314     if (![documentView isKindOfClass:[WebHTMLView class]]) {
315         return NO;
316     }
317     WebHTMLView *webHTMLView = (WebHTMLView *)documentView;
318     return [webHTMLView _wasFirstResponderAtMouseDownTime:responder];
319 }
320
321 - (void)closeWindowSoon
322 {
323     [[_frame webView] performSelector:@selector(_closeWindow) withObject:nil afterDelay:0.0];
324 }
325
326 - (NSWindow *)window
327 {
328     ASSERT(_frame != nil);
329     return [[_frame frameView] window];
330 }
331
332 - (void)runJavaScriptAlertPanelWithMessage:(NSString *)message
333 {
334     WebView *wv = [_frame webView];
335     [[wv _UIDelegateForwarder] webView:wv runJavaScriptAlertPanelWithMessage:message];
336 }
337
338 - (BOOL)runJavaScriptConfirmPanelWithMessage:(NSString *)message
339 {
340     WebView *wv = [_frame webView];
341     id wd = [wv UIDelegate];
342     if ([wd respondsToSelector: @selector(webView:runJavaScriptConfirmPanelWithMessage:)])
343         return [wd webView:wv runJavaScriptConfirmPanelWithMessage:message];
344     return [[WebDefaultUIDelegate sharedUIDelegate] webView:wv runJavaScriptConfirmPanelWithMessage:message];
345 }
346
347 - (BOOL)runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText returningText:(NSString **)result
348 {
349     WebView *wv = [_frame webView];
350     id wd = [wv UIDelegate];
351     if ([wd respondsToSelector: @selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:)])
352         *result = [wd webView:wv runJavaScriptTextInputPanelWithPrompt:prompt defaultText:defaultText];
353     else
354         *result = [[WebDefaultUIDelegate sharedUIDelegate] webView:wv runJavaScriptTextInputPanelWithPrompt:prompt defaultText:defaultText];
355     return *result != nil;
356 }
357
358 - (void)addMessageToConsole:(NSDictionary *)message
359 {
360     WebView *wv = [_frame webView];
361     id wd = [wv UIDelegate];
362     if ([wd respondsToSelector: @selector(webView:addMessageToConsole:)])
363         [wd webView:wv addMessageToConsole:message];
364 }
365
366 - (NSView <WebCoreFileButton> *)fileButtonWithDelegate:(id <WebCoreFileButtonDelegate>)delegate
367 {
368     return [[WebFileButton alloc] initWithBridge:self delegate:delegate];
369 }
370
371 - (void)runOpenPanelForFileButtonWithResultListener:(id<WebOpenPanelResultListener>)resultListener
372 {
373     WebView *wv = [_frame webView];
374     [[wv _UIDelegateForwarder] webView:wv runOpenPanelForFileButtonWithResultListener:resultListener];
375 }
376
377
378 - (WebDataSource *)dataSource
379 {
380     ASSERT(_frame != nil);
381     WebDataSource *dataSource = [_frame dataSource];
382
383     ASSERT(dataSource != nil);
384     ASSERT([dataSource _isCommitted]);
385
386     return dataSource;
387 }
388
389 - (void)setTitle:(NSString *)title
390 {
391     [[self dataSource] _setTitle:[title _web_stringByCollapsingNonPrintingCharacters]];
392 }
393
394 - (void)setStatusText:(NSString *)status
395 {
396     ASSERT(_frame != nil);
397     WebView *wv = [_frame webView];
398     [[wv _UIDelegateForwarder] webView:wv setStatusText:status];
399 }
400
401 - (void)receivedData:(NSData *)data textEncodingName:(NSString *)textEncodingName
402 {
403     // Set the encoding. This only needs to be done once, but it's harmless to do it again later.
404     NSString *encoding = [[self dataSource] _overrideEncoding];
405     BOOL userChosen = encoding != nil;
406     if (encoding == nil) {
407         encoding = textEncodingName;
408     }
409     [self setEncoding:encoding userChosen:userChosen];
410
411     [self addData:data];
412 }
413
414 - (id <WebCoreResourceHandle>)startLoadingResource:(id <WebCoreResourceLoader>)resourceLoader withURL:(NSURL *)URL customHeaders:(NSDictionary *)customHeaders
415 {
416     // If we are no longer attached to a WebView, this must be an attempted load from an
417     // onUnload handler, so let's just block it.
418     if ([[self dataSource] _webView] == nil) {
419         return nil;
420     }
421
422     return [WebSubresourceClient startLoadingResource:resourceLoader
423                                               withURL:URL
424                                         customHeaders:customHeaders
425                                              referrer:[self referrer]
426                                         forDataSource:[self dataSource]];
427 }
428
429 - (id <WebCoreResourceHandle>)startLoadingResource:(id <WebCoreResourceLoader>)resourceLoader withURL:(NSURL *)URL customHeaders:(NSDictionary *)customHeaders postData:(NSArray *)postData
430 {
431     // If we are no longer attached to a WebView, this must be an attempted load from an
432     // onUnload handler, so let's just block it.
433     if ([[self dataSource] _webView] == nil) {
434         return nil;
435     }
436
437     return [WebSubresourceClient startLoadingResource:resourceLoader
438                                               withURL:URL
439                                         customHeaders:customHeaders
440                                              postData:postData
441                                              referrer:[self referrer]
442                                         forDataSource:[self dataSource]];
443 }
444
445 - (void)objectLoadedFromCacheWithURL:(NSURL *)URL response:(NSURLResponse *)response data:(NSData *)data
446 {
447     WebResource *resource = [[WebResource alloc] initWithData:data
448                                                           URL:URL
449                                                      MIMEType:[response MIMEType]
450                                              textEncodingName:[response textEncodingName]
451                                                     frameName:nil];
452     ASSERT(resource != nil);
453     [[self dataSource] addSubresource:resource];
454     [resource release];
455     
456     [_frame _sendResourceLoadDelegateMessagesForURL:URL response:response length:[data length]];    
457 }
458
459 - (NSData *)syncLoadResourceWithURL:(NSURL *)URL customHeaders:(NSDictionary *)requestHeaders postData:(NSArray *)postData finalURL:(NSURL **)finalURL responseHeaders:(NSDictionary **)responseHeaderDict statusCode:(int *)statusCode
460 {
461     NSMutableURLRequest *newRequest = [[NSMutableURLRequest alloc] initWithURL:URL];
462
463     if (postData) {
464         [newRequest setHTTPMethod:@"POST"];
465         
466         // FIXME: This will have to be expanded to handle filenames and arrays with more than one element to fix file uploading.
467         if ([postData count] == 1 && [[postData objectAtIndex:0] isKindOfClass:[NSData class]]) {
468             [newRequest setHTTPBody:(NSData *)[postData objectAtIndex:0]];
469         }
470     }
471
472     NSEnumerator *e = [requestHeaders keyEnumerator];
473     NSString *key;
474     while ((key = (NSString *)[e nextObject]) != nil) {
475         [newRequest addValue:[requestHeaders objectForKey:key] forHTTPHeaderField:key];
476     }
477     
478     // Never use cached data for these requests (xmlhttprequests).
479     [newRequest setCachePolicy:[[[self dataSource] request] cachePolicy]];
480     [newRequest setHTTPReferrer:[self referrer]];
481     
482     WebView *webView = [_frame webView];
483     [newRequest setMainDocumentURL:[[[[webView mainFrame] dataSource] request] URL]];
484     [newRequest setHTTPUserAgent:[webView userAgentForURL:[newRequest URL]]];
485
486     NSURLResponse *response = nil;
487     NSError *error = nil;
488     NSData *result = [NSURLConnection sendSynchronousRequest:newRequest returningResponse:&response error:&error];
489
490     if (error == nil) {
491         *finalURL = [response URL];
492         if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
493                 NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; 
494                 *responseHeaderDict = [httpResponse allHeaderFields];
495                 *statusCode = [httpResponse statusCode];
496         } else {
497             *responseHeaderDict = [NSDictionary dictionary];
498             *statusCode = 200;
499         }
500     } else {
501         *finalURL = URL;
502         *responseHeaderDict = [NSDictionary dictionary];
503         *statusCode = 404;
504     }
505
506     // notify the delegates
507     [self objectLoadedFromCacheWithURL:URL response:response data:result];
508
509     return result;
510 }
511
512 - (BOOL)isReloading
513 {
514     return [[[self dataSource] request] cachePolicy] == NSURLRequestReloadIgnoringCacheData;
515 }
516
517 // We would like a better value for a maximum time_t,
518 // but there is no way to do that in C with any certainty.
519 // INT_MAX should work well enough for our purposes.
520 #define MAX_TIME_T ((time_t)INT_MAX)    
521
522 - (time_t)expiresTimeForResponse:(NSURLResponse *)response
523 {
524     // This check can be removed when the new Foundation method
525     // has been around long enough for everyone to have it.
526     if ([response respondsToSelector:@selector(_calculatedExpiration)]) {
527         NSTimeInterval expiration = [response _calculatedExpiration];
528         expiration += kCFAbsoluteTimeIntervalSince1970;
529         return expiration > MAX_TIME_T ? MAX_TIME_T : expiration;
530     }
531
532     // Fall back to the older calculation
533     time_t now = time(NULL);
534     NSTimeInterval lifetime = [response _freshnessLifetime];
535     if (lifetime < 0)
536         lifetime = 0;
537     
538     if (now + lifetime > MAX_TIME_T)
539         return MAX_TIME_T;
540     
541     return now + lifetime;
542 }
543
544 - (void)reportClientRedirectToURL:(NSURL *)URL delay:(NSTimeInterval)seconds fireDate:(NSDate *)date lockHistory:(BOOL)lockHistory isJavaScriptFormAction:(BOOL)isJavaScriptFormAction
545 {
546     [_frame _clientRedirectedTo:URL delay:seconds fireDate:date lockHistory:lockHistory isJavaScriptFormAction:(BOOL)isJavaScriptFormAction];
547 }
548
549 - (void)reportClientRedirectCancelled:(BOOL)cancelWithLoadInProgress
550 {
551     [_frame _clientRedirectCancelled:cancelWithLoadInProgress];
552 }
553
554 - (void)close
555 {
556     _frame = nil;
557 }
558
559 - (void)focusWindow
560 {
561     [[[_frame webView] _UIDelegateForwarder] webViewFocus:[_frame webView]];
562 }
563
564 - (void)unfocusWindow
565 {
566     if ([[self window] isKeyWindow] || [[[self window] attachedSheet] isKeyWindow]) {
567         [NSApp _cycleWindowsReversed:FALSE];
568     }
569 }
570
571 - (void)setIconURL:(NSURL *)URL
572 {
573     [[self dataSource] _setIconURL:URL];
574 }
575
576 - (void)setIconURL:(NSURL *)URL withType:(NSString *)type
577 {
578     [[self dataSource] _setIconURL:URL withType:type];
579 }
580
581 - (BOOL)canTargetLoadInFrame:(WebFrame *)targetFrame
582 {
583     // This method prevents this exploit:
584     // <rdar://problem/3715785> multiple frame injection vulnerability reported by Secunia, affects almost all browsers
585     
586     // don't mess with navigation purely within the same frame
587     if ([[self webFrame] webView] == [targetFrame webView]) {
588         return YES;
589     }
590
591     // Normally, domain should be called on the DOMDocument since it is a DOM method, but this fix is needed for
592     // Jaguar as well where the DOM API doesn't exist.
593     NSString *thisDomain = [self domain];
594     if ([thisDomain length] == 0) {
595         // Allow if the request is made from a local file.
596         return YES;
597     }
598     
599     WebFrame *parentFrame = [targetFrame parentFrame];
600     if (parentFrame == nil) {
601         // Allow if target is an entire window.
602         return YES;
603     }
604     
605     NSString *parentDomain = [[parentFrame _bridge] domain];
606     if (parentDomain != nil && [thisDomain _web_isCaseInsensitiveEqualToString:parentDomain]) {
607         // Allow if the domain of the parent of the targeted frame equals this domain.
608         return YES;
609     }
610
611     return NO;
612 }
613
614 - (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
615 {
616     if ([target length] == 0) {
617         target = nil;
618     }
619
620     WebFrame *targetFrame = [_frame findFrameNamed:target];
621     if (![self canTargetLoadInFrame:targetFrame]) {
622         return;
623     }
624     
625     WebFrameLoadType loadType;
626     
627     if (reload)
628         loadType = WebFrameLoadTypeReload;
629     else if (!forUser)
630         loadType = WebFrameLoadTypeInternal;
631     else
632         loadType = WebFrameLoadTypeStandard;
633     [_frame _loadURL:URL referrer:referrer loadType:loadType target:target triggeringEvent:event form:form formValues:values];
634
635     if (targetFrame != nil && _frame != targetFrame) {
636         [[targetFrame _bridge] focusWindow];
637     }
638 }
639
640 - (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
641 {
642     if ([target length] == 0) {
643         target = nil;
644     }
645
646     WebFrame *targetFrame = [_frame findFrameNamed:target];
647     if (![self canTargetLoadInFrame:targetFrame]) {
648         return;
649     }
650
651     [_frame _postWithURL:URL referrer:referrer target:target data:postData contentType:contentType triggeringEvent:event form:form formValues:values];
652
653     if (targetFrame != nil && _frame != targetFrame) {
654         [[targetFrame _bridge] focusWindow];
655     }
656 }
657
658 - (NSString *)generateFrameName
659 {
660     return [_frame _generateFrameName];
661 }
662
663 - (WebCoreBridge *)createChildFrameNamed:(NSString *)frameName withURL:(NSURL *)URL
664     renderPart:(KHTMLRenderPart *)childRenderPart
665     allowsScrolling:(BOOL)allowsScrolling marginWidth:(int)width marginHeight:(int)height
666 {
667     ASSERT(_frame != nil);
668     WebFrame *newFrame = [[_frame webView] _createFrameNamed:frameName inParent:_frame allowsScrolling:allowsScrolling];
669     if (newFrame == nil) {
670         return nil;
671     }
672     
673     [[newFrame _bridge] setRenderPart:childRenderPart];
674
675     [[newFrame frameView] _setMarginWidth:width];
676     [[newFrame frameView] _setMarginHeight:height];
677
678     [_frame _loadURL:URL intoChild:newFrame];
679
680     return [newFrame _bridge];
681 }
682
683 - (void)saveDocumentState: (NSArray *)documentState
684 {
685     WebHistoryItem *item = [_frame _itemForSavingDocState];
686     LOG(Loading, "%@: saving form state from to 0x%x", [_frame name], item);
687     if (item) {
688         [item setDocumentState: documentState];
689         // You might think we could save the scroll state here too, but unfortunately this
690         // often gets called after WebFrame::_transitionToCommitted has restored the scroll
691         // position of the next document.
692     }
693 }
694
695 - (NSArray *)documentState
696 {
697     LOG(Loading, "%@: restoring form state from item 0x%x", [_frame name], [_frame _itemForRestoringDocState]);
698     return [[_frame _itemForRestoringDocState] documentState];
699 }
700
701 - (BOOL)saveDocumentToPageCache: documentInfo
702 {
703     WebHistoryItem *item = [_frame _itemForSavingDocState];
704     if (![item hasPageCache]) {
705         return false;
706     }
707     [[item pageCache] setObject: documentInfo forKey: WebCorePageCacheStateKey];
708     return true;
709 }
710
711 - (NSString *)userAgentForURL:(NSURL *)URL
712 {
713     return [[_frame webView] userAgentForURL:URL];
714 }
715
716 - (BOOL)inNextKeyViewOutsideWebFrameViews
717 {
718     return _inNextKeyViewOutsideWebFrameViews;
719 }
720
721 - (NSView *)nextKeyViewOutsideWebFrameViews
722 {
723     _inNextKeyViewOutsideWebFrameViews = YES;
724     WebView *webView = [_frame webView];
725     // Do not ask webView for its next key view, but rather, ask it for 
726     // the next key view of the last view in its key view loop.
727     // Doing so gives us the correct answer as calculated by AppKit, 
728     // and makes HTML views behave like other views.
729     NSView *nextKeyView = [[webView _findLastViewInKeyViewLoop] nextKeyView];
730     _inNextKeyViewOutsideWebFrameViews = NO;
731     return nextKeyView;
732 }
733
734 - (NSView *)previousKeyViewOutsideWebFrameViews
735 {
736     WebView *webView = [_frame webView];
737     NSView *previousKeyView = [webView previousKeyView];
738     return previousKeyView;
739 }
740
741 - (BOOL)defersLoading
742 {
743     return [[_frame webView] defersCallbacks];
744 }
745
746 - (void)setDefersLoading:(BOOL)defers
747 {
748     [[_frame webView] setDefersCallbacks:defers];
749 }
750
751 - (void)setNeedsReapplyStyles
752 {
753     NSView <WebDocumentView> *view = [[_frame frameView] documentView];
754     if ([view isKindOfClass:[WebHTMLView class]]) {
755         [(WebHTMLView *)view setNeedsToApplyStyles:YES];
756         [view setNeedsLayout:YES];
757         [view setNeedsDisplay:YES];
758     }
759 }
760
761 - (void)tokenizerProcessedData
762 {
763     [_frame _checkLoadComplete];
764 }
765
766 // OK to be an NSString rather than an NSURL.
767 // This URL is only used for coloring visited links.
768 - (NSString *)requestedURLString
769 {
770     return [[[[self dataSource] request] URL] _web_originalDataAsString];
771 }
772
773 - (NSString *)incomingReferrer
774 {
775     return [[[self dataSource] request] HTTPReferrer];
776 }
777
778 - (NSView *)pluginViewWithPackage:(WebPluginPackage *)pluginPackage
779                    attributeNames:(NSArray *)attributeNames
780                   attributeValues:(NSArray *)attributeValues
781                           baseURL:(NSURL *)baseURL
782 {
783     WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
784     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
785         
786     WebPluginController *pluginController = [docView _pluginController];
787     
788     // Store attributes in a dictionary so they can be passed to WebPlugins.
789     NSMutableDictionary *attributes = [[NSMutableDictionary alloc] init];
790     unsigned count = [attributeNames count];
791     unsigned i;
792     for (i = 0; i < count; i++) {
793         [attributes setObject:[attributeValues objectAtIndex:i] forKey:[attributeNames objectAtIndex:i]];
794     }    
795     
796     [pluginPackage load];
797     Class viewFactory = [pluginPackage viewFactory];
798     
799     NSView *view = nil;
800     NSDictionary *arguments = nil;
801     
802     if ([viewFactory respondsToSelector:@selector(plugInViewWithArguments:)]) {
803         arguments = [NSDictionary dictionaryWithObjectsAndKeys:
804             baseURL, WebPlugInBaseURLKey,
805             attributes, WebPlugInAttributesKey,
806             pluginController, WebPlugInContainerKey,
807             [NSNumber numberWithInt:WebPlugInModeEmbed], WebPlugInModeKey,
808             nil];
809         LOG(Plugins, "arguments:\n%@", arguments);
810     } else if ([viewFactory respondsToSelector:@selector(pluginViewWithArguments:)]) {
811         arguments = [NSDictionary dictionaryWithObjectsAndKeys:
812             baseURL, WebPluginBaseURLKey,
813             attributes, WebPluginAttributesKey,
814             pluginController, WebPluginContainerKey,
815             nil];
816         LOG(Plugins, "arguments:\n%@", arguments);
817     }
818     
819     view = [WebPluginController plugInViewWithArguments:arguments fromPluginPackage:pluginPackage];
820     
821     [attributes release];
822     return view;
823 }
824
825 - (NSString *)valueForKey:(NSString *)key keys:(NSArray *)keys values:(NSArray *)values
826 {
827     unsigned count = [keys count];
828     unsigned i;
829     for (i = 0; i < count; i++) {
830         if ([[keys objectAtIndex:i] _web_isCaseInsensitiveEqualToString:key]) {
831             return [values objectAtIndex:i];
832         }
833     }
834     return nil;
835 }
836
837 - (NSView *)viewForPluginWithURL:(NSURL *)URL
838                   attributeNames:(NSArray *)attributeNames
839                  attributeValues:(NSArray *)attributeValues
840                         MIMEType:(NSString *)MIMEType
841 {
842     ASSERT([attributeNames count] == [attributeValues count]);
843
844     WebBasePluginPackage *pluginPackage = nil;
845     NSView *view = nil;
846     int errorCode = 0;
847     
848     if ([MIMEType length] != 0) {
849         pluginPackage = [[WebPluginDatabase installedPlugins] pluginForMIMEType:MIMEType];
850     } else {
851         MIMEType = nil;
852     }
853     
854     NSString *extension = [[URL path] pathExtension];
855     if (!pluginPackage && [extension length] != 0) {
856         pluginPackage = [[WebPluginDatabase installedPlugins] pluginForExtension:extension];
857         if (pluginPackage) {
858             NSString *newMIMEType = [pluginPackage MIMETypeForExtension:extension];
859             if ([newMIMEType length] != 0) {
860                 MIMEType = newMIMEType;
861             }
862         }
863     }
864
865     NSURL *baseURL = [[[_frame dataSource] response] URL];
866     if (pluginPackage) {
867         if ([pluginPackage isKindOfClass:[WebPluginPackage class]]) {
868             view = [self pluginViewWithPackage:(WebPluginPackage *)pluginPackage
869                                 attributeNames:attributeNames
870                                attributeValues:attributeValues
871                                        baseURL:baseURL];
872         } else if ([pluginPackage isKindOfClass:[WebNetscapePluginPackage class]]) {
873             view = [[[WebNetscapePluginEmbeddedView alloc] initWithFrame:NSZeroRect
874                                                                   plugin:(WebNetscapePluginPackage *)pluginPackage
875                                                                      URL:URL
876                                                                  baseURL:baseURL
877                                                                 MIMEType:MIMEType
878                                                            attributeKeys:attributeNames
879                                                          attributeValues:attributeValues] autorelease];
880         } else {
881             ASSERT_NOT_REACHED();
882         }
883     } else {
884         errorCode = WebKitErrorCannotFindPlugIn;
885     }
886
887     if (!errorCode && !view) {
888         errorCode = WebKitErrorCannotLoadPlugIn;
889     }
890
891     if (errorCode) {
892         NSString *pluginPage = [self valueForKey:@"pluginspage" keys:attributeNames values:attributeValues];
893         NSURL *pluginPageURL = pluginPage != nil ? [self URLWithAttributeString:pluginPage] : nil;
894         NSError *error = [[NSError alloc] _initWithPluginErrorCode:errorCode
895                                                         contentURL:URL
896                                                      pluginPageURL:pluginPageURL
897                                                         pluginName:[pluginPackage name]
898                                                           MIMEType:MIMEType];
899         view = [[[WebNullPluginView alloc] initWithFrame:NSZeroRect error:error] autorelease];
900         [error release];
901     }
902     
903     ASSERT(view);
904     return view;
905 }
906
907 - (NSView *)viewForJavaAppletWithFrame:(NSRect)theFrame
908                         attributeNames:(NSArray *)attributeNames
909                        attributeValues:(NSArray *)attributeValues
910                                baseURL:(NSURL *)baseURL;
911 {
912     NSString *MIMEType = @"application/x-java-applet";
913     WebBasePluginPackage *pluginPackage;
914     NSView *view = nil;
915     
916     pluginPackage = [[WebPluginDatabase installedPlugins] pluginForMIMEType:MIMEType];
917
918     if (pluginPackage) {
919         if ([pluginPackage isKindOfClass:[WebPluginPackage class]]) {
920             // For some reason, the Java plug-in requires that we pass the dimension of the plug-in as attributes.
921             NSMutableArray *names = [attributeNames mutableCopy];
922             NSMutableArray *values = [attributeValues mutableCopy];
923             if ([self valueForKey:@"width" keys:attributeNames values:attributeValues] == nil) {
924                 [names addObject:@"width"];
925                 [values addObject:[NSString stringWithFormat:@"%d", (int)theFrame.size.width]];
926             }
927             if ([self valueForKey:@"height" keys:attributeNames values:attributeValues] == nil) {
928                 [names addObject:@"height"];
929                 [values addObject:[NSString stringWithFormat:@"%d", (int)theFrame.size.height]];
930             }
931             view = [self pluginViewWithPackage:(WebPluginPackage *)pluginPackage
932                                 attributeNames:names
933                                attributeValues:values
934                                        baseURL:baseURL];
935             [names release];
936             [values release];
937         } else if ([pluginPackage isKindOfClass:[WebNetscapePluginPackage class]]) {
938             view = [[[WebNetscapePluginEmbeddedView alloc] initWithFrame:theFrame
939                                                                   plugin:(WebNetscapePluginPackage *)pluginPackage
940                                                                      URL:nil
941                                                                  baseURL:baseURL
942                                                                 MIMEType:MIMEType
943                                                            attributeKeys:attributeNames
944                                                          attributeValues:attributeValues] autorelease];
945         } else {
946             ASSERT_NOT_REACHED();
947         }
948     }
949
950     if (!view) {
951         NSError *error = [[NSError alloc] _initWithPluginErrorCode:WebKitErrorJavaUnavailable
952                                                         contentURL:nil
953                                                      pluginPageURL:nil
954                                                         pluginName:[pluginPackage name]
955                                                           MIMEType:MIMEType];
956         view = [[[WebNullPluginView alloc] initWithFrame:theFrame error:error] autorelease];
957         [error release];
958     }
959
960     ASSERT(view);
961
962     return view;
963 }
964
965 #ifndef NDEBUG
966 static BOOL loggedObjectCacheSize = NO;
967 #endif
968
969
970 -(int)getObjectCacheSize
971 {
972     vm_size_t memSize = WebSystemMainMemory();
973     int cacheSize = [[WebPreferences standardPreferences] _objectCacheSize];
974     int multiplier = 1;
975     if (memSize >= 1024 * 1024 * 1024)
976         multiplier = 4;
977     else if (memSize >= 512 * 1024 * 1024)
978         multiplier = 2;
979
980 #ifndef NDEBUG
981     if (!loggedObjectCacheSize){
982         LOG (CacheSizes, "Object cache size set to %d bytes.", cacheSize * multiplier);
983         loggedObjectCacheSize = YES;
984     }
985 #endif
986
987     return cacheSize * multiplier;
988 }
989
990 - (BOOL)frameRequiredForMIMEType:(NSString *)MIMEType URL:(NSURL *)URL
991 {
992     if ([MIMEType length] == 0) {
993         NSString *extension = [[URL path] pathExtension];
994         if ([extension length] > 0 && [[WebPluginDatabase installedPlugins] pluginForExtension:extension] != nil) {
995             // If no MIME type is specified, use a plug-in if we have one that can handle the extension.
996             return NO;
997         } else {
998             // Else, create a frame and attempt to load the URL in there.
999             return YES;
1000         }
1001     }
1002     
1003     Class viewClass = [WebFrameView _viewClassForMIMEType:MIMEType];
1004     if (!viewClass) {
1005         // Want to display a "plugin not found" dialog/image, so let a plugin get made.
1006         return NO;
1007     }
1008         
1009     // If we're a supported type other than a plugin, we want to make a frame.
1010     // Ultimately we should just use frames for all mime types (plugins and HTML/XML/text documents),
1011     // but for now we're burdened with making a distinction between the two.
1012     return !([viewClass isSubclassOfClass:[WebNetscapePluginDocumentView class]] || 
1013              [viewClass isSubclassOfClass:[WebPluginDocumentView class]]);
1014 }
1015
1016 - (void)loadEmptyDocumentSynchronously
1017 {
1018     NSURL *url = [[NSURL alloc] initWithString:@""];
1019     NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
1020     [_frame loadRequest:request];
1021     [request release];
1022     [url release];
1023 }
1024
1025 - (NSString *)MIMETypeForPath:(NSString *)path
1026 {
1027     ASSERT(path);
1028     NSString *extension = [path pathExtension];
1029     NSString *type = [[NSURLFileTypeMappings sharedMappings] MIMETypeForExtension:extension];
1030     return [type length] == 0 ? @"application/octet-stream" : type;
1031 }
1032
1033 - (void)allowDHTMLDrag:(BOOL *)flagDHTML UADrag:(BOOL *)flagUA
1034 {
1035     WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
1036     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
1037     unsigned int mask = [docView _delegateDragSourceActionMask];
1038     *flagDHTML = (mask & WebDragSourceActionDHTML) != 0;
1039     *flagUA = ((mask & WebDragSourceActionImage) || (mask & WebDragSourceActionLink) || (mask & WebDragSourceActionSelection));
1040 }
1041
1042 - (BOOL)startDraggingImage:(NSImage *)dragImage at:(NSPoint)dragLoc operation:(NSDragOperation)op event:(NSEvent *)event sourceIsDHTML:(BOOL)flag DHTMLWroteData:(BOOL)dhtmlWroteData
1043 {
1044     WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
1045     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
1046     return [docView _startDraggingImage:dragImage at:dragLoc operation:op event:event sourceIsDHTML:flag DHTMLWroteData:dhtmlWroteData];
1047 }
1048
1049 - (void)handleAutoscrollForMouseDragged:(NSEvent *)event;
1050 {
1051     WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
1052
1053     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
1054
1055     [docView _handleAutoscrollForMouseDragged:event];
1056 }
1057
1058 - (BOOL)mayStartDragAtEventLocation:(NSPoint)location
1059 {
1060     WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
1061
1062     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
1063
1064     return [docView _mayStartDragAtEventLocation:location];
1065 }
1066
1067 - (int)historyLength
1068 {
1069     return [[[_frame webView] backForwardList] backListCount] + 1;
1070 }
1071
1072 - (BOOL)canGoBackOrForward:(int)distance
1073 {
1074     if (distance == 0)
1075         return TRUE;
1076
1077     if (distance > 0 && distance <= [[[_frame webView] backForwardList] forwardListCount])
1078         return TRUE;
1079
1080     if (distance < 0 && -distance <= [[[_frame webView] backForwardList] backListCount])
1081         return TRUE;
1082     
1083     return FALSE;
1084 }
1085
1086 - (void)goBackOrForward:(int)distance
1087 {
1088     if (distance == 0) {
1089         return;
1090     }
1091     WebView *webView = [_frame webView];
1092     WebBackForwardList *list = [webView backForwardList];
1093     WebHistoryItem *item = [list itemAtIndex:distance];
1094     if (!item) {
1095         if (distance > 0) {
1096             int forwardListCount = [list forwardListCount];
1097             if (forwardListCount > 0) {
1098                 item = [list itemAtIndex:forwardListCount];
1099             }
1100         } else {
1101             int backListCount = [list forwardListCount];
1102             if (backListCount > 0) {
1103                 item = [list itemAtIndex:-backListCount];
1104             }
1105         }
1106     }
1107     if (item) {
1108         [webView goToBackForwardItem:item];
1109     }
1110 }
1111
1112 static id <WebFormDelegate> formDelegate(WebBridge *self)
1113 {
1114     ASSERT(self->_frame != nil);
1115     return [[self->_frame webView] _formDelegate];
1116 }
1117
1118 #define FormDelegateLog(ctrl)  LOG(FormDelegate, "control=%@", ctrl)
1119
1120 - (void)controlTextDidBeginEditing:(NSNotification *)obj
1121 {
1122     FormDelegateLog([obj object]);
1123     [formDelegate(self) controlTextDidBeginEditing:obj inFrame:_frame];
1124 }
1125
1126 - (void)controlTextDidEndEditing:(NSNotification *)obj
1127 {
1128     FormDelegateLog([obj object]);
1129     [formDelegate(self) controlTextDidEndEditing:obj inFrame:_frame];
1130 }
1131
1132 - (void)controlTextDidChange:(NSNotification *)obj
1133 {
1134     FormDelegateLog([obj object]);
1135     [formDelegate(self) controlTextDidChange:obj inFrame:_frame];
1136 }
1137
1138 - (BOOL)control:(NSControl *)control textShouldBeginEditing:(NSText *)fieldEditor
1139 {
1140     FormDelegateLog(control);
1141     return [formDelegate(self) control:control textShouldBeginEditing:fieldEditor inFrame:_frame];
1142 }
1143
1144 - (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor
1145 {
1146     FormDelegateLog(control);
1147     return [formDelegate(self) control:control textShouldEndEditing:fieldEditor inFrame:_frame];
1148 }
1149
1150 - (BOOL)control:(NSControl *)control didFailToFormatString:(NSString *)string errorDescription:(NSString *)error
1151 {
1152     FormDelegateLog(control);
1153     return [formDelegate(self) control:control didFailToFormatString:string errorDescription:error inFrame:_frame];
1154 }
1155
1156 - (void)control:(NSControl *)control didFailToValidatePartialString:(NSString *)string errorDescription:(NSString *)error
1157 {
1158     FormDelegateLog(control);
1159     [formDelegate(self) control:control didFailToValidatePartialString:string errorDescription:error inFrame:_frame];
1160 }
1161
1162 - (BOOL)control:(NSControl *)control isValidObject:(id)obj
1163 {
1164     FormDelegateLog(control);
1165     return [formDelegate(self) control:control isValidObject:obj inFrame:_frame];
1166 }
1167
1168 - (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector
1169 {
1170     FormDelegateLog(control);
1171     return [formDelegate(self) control:control textView:textView doCommandBySelector:commandSelector inFrame:_frame];
1172 }
1173
1174 - (BOOL)control:(NSControl *)control textView:(NSTextView *)textView shouldHandleEvent:(NSEvent *)event
1175 {
1176     FormDelegateLog(control);
1177     return [formDelegate(self) control:control textView:textView shouldHandleEvent:event inFrame:_frame];
1178 }
1179
1180 - (void)frameDetached
1181 {
1182     // Put _frame into a local variable because _detachFromParent
1183     // will disconnect the bridge from the frame and make _frame nil.
1184     WebFrame *frame = _frame;
1185
1186     [frame stopLoading];
1187     [frame _detachFromParent];
1188     [[frame parentFrame] _removeChild:frame];
1189 }
1190
1191 - (void)setHasBorder:(BOOL)hasBorder
1192 {
1193     [[_frame frameView] _setHasBorder:hasBorder];
1194 }
1195
1196 - (void)_retrieveKeyboardUIModeFromPreferences:(NSNotification *)notification
1197 {
1198     CFPreferencesAppSynchronize(UniversalAccessDomain);
1199
1200     BOOL keyExistsAndHasValidFormat;
1201     int mode = CFPreferencesGetAppIntegerValue(AppleKeyboardUIMode, UniversalAccessDomain, &keyExistsAndHasValidFormat);
1202     
1203     // The keyboard access mode is reported by two bits:
1204     // Bit 0 is set if feature is on
1205     // Bit 1 is set if full keyboard access works for any control, not just text boxes and lists
1206     // We require both bits to be on.
1207     // I do not know that we would ever get one bit on and the other off since
1208     // checking the checkbox in system preferences which is marked as "Turn on full keyboard access"
1209     // turns on both bits.
1210     _keyboardUIMode = (mode & 0x2) ? WebCoreKeyboardAccessFull : WebCoreKeyboardAccessDefault;
1211     
1212     // check for tabbing to links
1213     if ([[WebPreferences standardPreferences] tabsToLinks]) {
1214         _keyboardUIMode |= WebCoreKeyboardAccessTabsToLinks;
1215     }
1216 }
1217
1218 - (WebCoreKeyboardUIMode)keyboardUIMode
1219 {
1220     if (!_keyboardUIModeAccessed) {
1221         _keyboardUIModeAccessed = YES;
1222         [self _retrieveKeyboardUIModeFromPreferences:nil];
1223         
1224         [[NSDistributedNotificationCenter defaultCenter] 
1225             addObserver:self selector:@selector(_retrieveKeyboardUIModeFromPreferences:) 
1226             name:KeyboardUIModeDidChangeNotification object:nil];
1227
1228         [[NSNotificationCenter defaultCenter] 
1229             addObserver:self selector:@selector(_retrieveKeyboardUIModeFromPreferences:) 
1230                    name:WebPreferencesChangedNotification object:nil];
1231     }
1232     return _keyboardUIMode;
1233 }
1234
1235 - (void)didSetName:(NSString *)name
1236 {
1237     [_frame _setName:name];
1238 }
1239
1240 - (NSFileWrapper *)fileWrapperForURL:(NSURL *)URL
1241 {
1242     return [[_frame dataSource] _fileWrapperForURL:URL];
1243 }
1244
1245 - (void)print
1246 {
1247     id wd = [[_frame webView] UIDelegate];
1248     
1249     if ([wd respondsToSelector:@selector(webView:printFrameView:)]) {
1250         [wd webView:[_frame webView] printFrameView:[_frame frameView]];
1251     } else if ([wd respondsToSelector:@selector(webViewPrint:)]) {
1252         // Backward-compatible, but webViewPrint: was never public, so probably not needed.
1253         [wd webViewPrint:[_frame webView]];
1254     } else {
1255         [[WebDefaultUIDelegate sharedUIDelegate] webView:[_frame webView] printFrameView:[_frame frameView]];
1256     }
1257 }
1258
1259 - (jobject)getAppletInView:(NSView *)view
1260 {
1261     jobject applet = 0;
1262
1263     if ([view respondsToSelector: @selector(webPlugInGetApplet)])
1264         applet = [view webPlugInGetApplet];
1265     else
1266         applet = [self pollForAppletInView:view];
1267         
1268     return applet;
1269 }
1270
1271 // NOTE: pollForAppletInView: will block until the block is ready to use, or
1272 // until a timeout is exceeded.  It will return nil if the timeour is
1273 // exceeded.
1274 // Deprecated, use getAppletInView:.
1275 - (jobject)pollForAppletInView: (NSView *)view
1276 {
1277     jobject applet = 0;
1278     
1279     if ([view respondsToSelector: @selector(pollForAppletInWindow:)]) {
1280         // The Java VM needs the containing window of the view to
1281         // initialize.  The view may not yet be in the window's view 
1282         // hierarchy, so we have to pass the window when requesting
1283         // the applet.
1284         applet = [view pollForAppletInWindow:[[_frame webView] window]];
1285     }
1286     
1287     return applet;
1288 }
1289
1290 - (void)respondToChangedContents
1291 {
1292     NSView <WebDocumentView> *view = [[_frame frameView] documentView];
1293     if ([view isKindOfClass:[WebHTMLView class]]) {
1294         [(WebHTMLView *)view _updateFontPanel];
1295     }
1296     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewDidChangeNotification object:[_frame webView]];
1297 }
1298
1299 - (void)respondToChangedSelection
1300 {
1301     NSView <WebDocumentView> *view = [[_frame frameView] documentView];
1302     if ([view isKindOfClass:[WebHTMLView class]]) {
1303         [(WebHTMLView *)view _selectionChanged];
1304     }
1305     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewDidChangeSelectionNotification object:[_frame webView]];
1306 }
1307
1308 - (NSUndoManager *)undoManager
1309 {
1310     return [[_frame webView] undoManager];
1311 }
1312
1313 - (void)issueCutCommand
1314 {
1315     [[_frame webView] cut:nil];
1316 }
1317
1318 - (void)issueCopyCommand
1319 {
1320     [[_frame webView] copy:nil];
1321 }
1322
1323 - (void)issuePasteCommand
1324 {
1325     [[_frame webView] paste:nil];
1326 }
1327
1328 - (BOOL)canPaste
1329 {
1330     return [[_frame webView] _canPaste];
1331 }
1332
1333 - (void)setIsSelected:(BOOL)isSelected forView:(NSView *)view
1334 {
1335     if ([view respondsToSelector:@selector(webPlugInSetIsSelected:)]) {
1336         [view webPlugInSetIsSelected:isSelected];
1337     }
1338     else if ([view respondsToSelector:@selector(setIsSelected:)]) {
1339         [view setIsSelected:isSelected];
1340     }
1341 }
1342
1343 - (NSString *)overrideMediaType
1344 {
1345     return [[_frame webView] mediaStyle];
1346 }
1347
1348 - (BOOL)isEditable
1349 {
1350     return [[_frame webView] isEditable];
1351 }
1352
1353 - (BOOL)shouldBeginEditing:(DOMRange *)range
1354 {
1355     return [[_frame webView] _shouldBeginEditingInDOMRange:range];
1356 }
1357
1358 - (BOOL)shouldEndEditing:(DOMRange *)range
1359 {
1360     return [[_frame webView] _shouldEndEditingInDOMRange:range];
1361 }
1362
1363 - (void)windowObjectCleared
1364 {
1365     WebView *wv = [_frame webView];
1366     [[wv _frameLoadDelegateForwarder] webView:wv windowScriptObjectAvailable:[self windowScriptObject]];
1367 }
1368
1369 - (int)spellCheckerDocumentTag
1370 {
1371     return [[_frame webView] spellCheckerDocumentTag];
1372 }
1373
1374 - (BOOL)isContinuousSpellCheckingEnabled
1375 {
1376     return [[_frame webView] isContinuousSpellCheckingEnabled];
1377 }
1378
1379 - (void)didFirstLayout
1380 {
1381     WebView *wv = [_frame webView];
1382     [[wv _frameLoadDelegateForwarder] webView:wv didFirstLayoutInFrame:_frame];
1383 }
1384
1385 - (void)dashboardRegionsChanged:(NSMutableDictionary *)regions
1386 {
1387     WebView *wv = [_frame webView];
1388     id wd = [wv UIDelegate];
1389     
1390     [wv _addScrollerDashboardRegions:regions];
1391     
1392     if ([wd respondsToSelector: @selector(webView:dashboardRegionsChanged:)]) {
1393         [wd webView:wv dashboardRegionsChanged:regions];
1394     }
1395 }
1396
1397 // This method exists to hold localizable strings for action names for the Undo menu item. It contains
1398 // all of the names used in NSTextView. We will wire some or all of these up eventually; for now we are
1399 // just putting them here to get them localized before the localization freeze for Tiger.
1400 - (NSString *)setUndoActionNamePlaceholder
1401 {
1402     int x = 0;
1403     switch (x) {
1404         case 0: return UI_STRING_KEY("Set Color", "Set Color (Undo action name)", "Undo action name");
1405         case 1: return UI_STRING_KEY("Set Background Color", "Set Background Color (Undo action name)", "Undo action name");
1406         case 2: return UI_STRING_KEY("Turn Off Kerning", "Turn Off Kerning (Undo action name)", "Undo action name");
1407         case 3: return UI_STRING_KEY("Tighten Kerning", "Tighten Kerning (Undo action name)", "Undo action name");
1408         case 4: return UI_STRING_KEY("Loosen Kerning", "Loosen Kerning (Undo action name)", "Undo action name");
1409         case 5: return UI_STRING_KEY("Use Standard Kerning", "Use Standard Kerning (Undo action name)", "Undo action name");
1410         case 6: return UI_STRING_KEY("Turn Off Ligatures", "Turn Off Ligatures (Undo action name)", "Undo action name");
1411         case 7: return UI_STRING_KEY("Use Standard Ligatures", "Use Standard Ligatures (Undo action name)", "Undo action name");
1412         case 8: return UI_STRING_KEY("Use All Ligatures", "Use All Ligatures (Undo action name)", "Undo action name");
1413         case 9: return UI_STRING_KEY("Raise Baseline", "Raise Baseline (Undo action name)", "Undo action name");
1414         case 10: return UI_STRING_KEY("Lower Baseline", "Lower Baseline (Undo action name)", "Undo action name");
1415         case 11: return UI_STRING_KEY("Set Traditional Character Shape", "Set Traditional Character Shape (Undo action name)", "Undo action name");
1416         case 12: return UI_STRING_KEY("Set Font", "Set Font (Undo action name)", "Undo action name");
1417         case 13: return UI_STRING_KEY("Change Attributes", "Change Attributes (Undo action name)", "Undo action name");
1418         case 14: return UI_STRING_KEY("Align Left", "Align Left (Undo action name)", "Undo action name");
1419         case 15: return UI_STRING_KEY("Align Right", "Align Right (Undo action name)", "Undo action name");
1420         case 16: return UI_STRING_KEY("Center", "Center (Undo action name)", "Undo action name");
1421         case 17: return UI_STRING_KEY("Justify", "Justify (Undo action name)", "Undo action name");
1422         case 18: return UI_STRING_KEY("Set Writing Direction", "Set Writing Direction (Undo action name)", "Undo action name");
1423         case 19: return UI_STRING_KEY("Set Color", "Set Color (Undo action name)", "Undo action name");
1424         case 20: return UI_STRING_KEY("Subscript", "Subscript (Undo action name)", "Undo action name");
1425         case 21: return UI_STRING_KEY("Superscript", "Superscript (Undo action name)", "Undo action name");
1426         case 22: return UI_STRING_KEY("Underline", "Underline (Undo action name)", "Undo action name");
1427         case 23: return UI_STRING_KEY("Outline", "Outline (Undo action name)", "Undo action name");
1428         case 24: return UI_STRING_KEY("Unscript", "Unscript (Undo action name)", "Undo action name");
1429         case 25: return UI_STRING_KEY("Drag", "Drag (Undo action name)", "Undo action name");
1430         case 26: return UI_STRING_KEY("Cut", "Cut (Undo action name)", "Undo action name");
1431         case 27: return UI_STRING_KEY("Paste", "Paste (Undo action name)", "Undo action name");
1432         case 28: return UI_STRING_KEY("Paste Font", "Paste Font (Undo action name)", "Undo action name");
1433         case 29: return UI_STRING_KEY("Paste Ruler", "Paste Ruler (Undo action name)", "Undo action name");
1434         case 30: return UI_STRING_KEY("Cut", "Cut (Undo action name)", "Undo action name");
1435         case 31: return UI_STRING_KEY("Typing", "Typing (Undo action name)", "Undo action name");
1436     }
1437     return nil;
1438 }
1439
1440 // FIXME: The following 2 functions are copied from AppKit. It would be best share code.
1441
1442 // MF:!!! For now we will use static character sets for the computation, but we should eventually probably make these keys in the language dictionaries.
1443 // 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).
1444 // 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).
1445 // MF:!!! Another difference in both of these sets from the old text object is we include all the whitespace in whitespaceAndNewlineCharacterSet.
1446 #define _preSmartString @"([\"\'#$/-`{"
1447 #define _postSmartString @")].,;:?\'!\"%*-/}"
1448
1449 static NSCharacterSet *_getPreSmartSet(void)
1450 {
1451     static NSMutableCharacterSet *_preSmartSet = nil;
1452     if (!_preSmartSet) {
1453         _preSmartSet = [[NSMutableCharacterSet characterSetWithCharactersInString:_preSmartString] retain];
1454         [_preSmartSet formUnionWithCharacterSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
1455         // Adding CJK ranges
1456         [_preSmartSet addCharactersInRange:NSMakeRange(0x1100, 256)]; // Hangul Jamo (0x1100 - 0x11FF)
1457         [_preSmartSet addCharactersInRange:NSMakeRange(0x2E80, 352)]; // CJK & Kangxi Radicals (0x2E80 - 0x2FDF)
1458         [_preSmartSet addCharactersInRange:NSMakeRange(0x2FF0, 464)]; // Ideograph Descriptions, CJK Symbols, Hiragana, Katakana, Bopomofo, Hangul Compatibility Jamo, Kanbun, & Bopomofo Ext (0x2FF0 - 0x31BF)
1459         [_preSmartSet addCharactersInRange:NSMakeRange(0x3200, 29392)]; // Enclosed CJK, CJK Ideographs (Uni Han & Ext A), & Yi (0x3200 - 0xA4CF)
1460         [_preSmartSet addCharactersInRange:NSMakeRange(0xAC00, 11183)]; // Hangul Syllables (0xAC00 - 0xD7AF)
1461         [_preSmartSet addCharactersInRange:NSMakeRange(0xF900, 352)]; // CJK Compatibility Ideographs (0xF900 - 0xFA5F)
1462         [_preSmartSet addCharactersInRange:NSMakeRange(0xFE30, 32)]; // CJK Compatibility From (0xFE30 - 0xFE4F)
1463         [_preSmartSet addCharactersInRange:NSMakeRange(0xFF00, 240)]; // Half/Full Width Form (0xFF00 - 0xFFEF)
1464         [_preSmartSet addCharactersInRange:NSMakeRange(0x20000, 0xA6D7)]; // CJK Ideograph Exntension B
1465         [_preSmartSet addCharactersInRange:NSMakeRange(0x2F800, 0x021E)]; // CJK Compatibility Ideographs (0x2F800 - 0x2FA1D)
1466     }
1467     return _preSmartSet;
1468 }
1469
1470 static NSCharacterSet *_getPostSmartSet(void)
1471 {
1472     static NSMutableCharacterSet *_postSmartSet = nil;
1473     if (!_postSmartSet) {
1474         _postSmartSet = [[NSMutableCharacterSet characterSetWithCharactersInString:_postSmartString] retain];
1475         [_postSmartSet formUnionWithCharacterSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
1476         [_postSmartSet addCharactersInRange:NSMakeRange(0x1100, 256)]; // Hangul Jamo (0x1100 - 0x11FF)
1477         [_postSmartSet addCharactersInRange:NSMakeRange(0x2E80, 352)]; // CJK & Kangxi Radicals (0x2E80 - 0x2FDF)
1478         [_postSmartSet addCharactersInRange:NSMakeRange(0x2FF0, 464)]; // Ideograph Descriptions, CJK Symbols, Hiragana, Katakana, Bopomofo, Hangul Compatibility Jamo, Kanbun, & Bopomofo Ext (0x2FF0 - 0x31BF)
1479         [_postSmartSet addCharactersInRange:NSMakeRange(0x3200, 29392)]; // Enclosed CJK, CJK Ideographs (Uni Han & Ext A), & Yi (0x3200 - 0xA4CF)
1480         [_postSmartSet addCharactersInRange:NSMakeRange(0xAC00, 11183)]; // Hangul Syllables (0xAC00 - 0xD7AF)
1481         [_postSmartSet addCharactersInRange:NSMakeRange(0xF900, 352)]; // CJK Compatibility Ideographs (0xF900 - 0xFA5F)
1482         [_postSmartSet addCharactersInRange:NSMakeRange(0xFE30, 32)]; // CJK Compatibility From (0xFE30 - 0xFE4F)
1483         [_postSmartSet addCharactersInRange:NSMakeRange(0xFF00, 240)]; // Half/Full Width Form (0xFF00 - 0xFFEF)
1484         [_postSmartSet addCharactersInRange:NSMakeRange(0x20000, 0xA6D7)]; // CJK Ideograph Exntension B
1485         [_postSmartSet addCharactersInRange:NSMakeRange(0x2F800, 0x021E)]; // CJK Compatibility Ideographs (0x2F800 - 0x2FA1D)        
1486         [_postSmartSet formUnionWithCharacterSet:[NSCharacterSet punctuationCharacterSet]];
1487     }
1488     return _postSmartSet;
1489 }
1490
1491 - (BOOL)isCharacterSmartReplaceExempt:(unichar)c isPreviousCharacter:(BOOL)isPreviousCharacter
1492 {
1493     return [isPreviousCharacter ? _getPreSmartSet() : _getPostSmartSet() characterIsMember:c];
1494 }
1495
1496 @end