Clean build fix after r17607: removed obselete header include.
[WebKit-https.git] / WebKit / WebCoreSupport / WebFrameBridge.mm
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 "WebBackForwardList.h"
32 #import "WebBaseNetscapePluginView.h"
33 #import "WebBasePluginPackage.h"
34 #import "WebDataSourceInternal.h"
35 #import "WebDefaultUIDelegate.h"
36 #import "WebEditingDelegate.h"
37 #import "WebEditorClient.h"
38 #import "WebFormDelegate.h"
39 #import "WebFrameInternal.h"
40 #import "WebFrameLoadDelegate.h"
41 #import "WebFrameViewInternal.h"
42 #import "WebHTMLRepresentationPrivate.h"
43 #import "WebHTMLViewInternal.h"
44 #import "WebHistoryItemPrivate.h"
45 #import "WebIconDatabase.h"
46 #import "WebIconDatabasePrivate.h"
47 #import "WebJavaPlugIn.h"
48 #import "WebJavaScriptTextInputPanel.h"
49 #import "WebKitErrorsPrivate.h"
50 #import "WebKitLogging.h"
51 #import "WebKitNSStringExtras.h"
52 #import "WebKitStatisticsPrivate.h"
53 #import "WebKitSystemBits.h"
54 #import "WebLocalizableStrings.h"
55 #import "WebNSObjectExtras.h"
56 #import "WebNSURLExtras.h"
57 #import "WebNSURLRequestExtras.h"
58 #import "WebNSViewExtras.h"
59 #import "WebNetscapePluginEmbeddedView.h"
60 #import "WebNetscapePluginPackage.h"
61 #import "WebNullPluginView.h"
62 #import "WebPageBridge.h"
63 #import "WebPlugin.h"
64 #import "WebPluginController.h"
65 #import "WebPluginDatabase.h"
66 #import "WebPluginPackage.h"
67 #import "WebPluginViewFactoryPrivate.h"
68 #import "WebPreferencesPrivate.h"
69 #import "WebResourcePrivate.h"
70 #import "WebScriptDebugServerPrivate.h"
71 #import "WebUIDelegatePrivate.h"
72 #import "WebViewInternal.h"
73 #import <Foundation/NSURLConnection.h>
74 #import <Foundation/NSURLRequest.h>
75 #import <Foundation/NSURLResponse.h>
76 #import <JavaScriptCore/Assertions.h>
77 #import <JavaVM/jni.h>
78 #import <WebCore/DocumentLoader.h>
79 #import <WebCore/FrameLoader.h>
80 #import <WebCore/FrameLoaderClient.h>
81 #import <WebCore/FrameMac.h>
82 #import <WebCore/FrameTree.h>
83 #import <WebCore/Page.h>
84 #import <WebCore/ResourceLoader.h>
85 #import <WebCore/SubresourceLoader.h>
86 #import <WebCore/WebCoreFrameNamespaces.h>
87 #import <WebCore/WebCoreSettings.h>
88 #import <WebKitSystemInterface.h>
89 #import <wtf/RefPtr.h>
90
91 // For compatibility with old SPI. 
92 @interface NSView (OldWebPlugin)
93 - (void)setIsSelected:(BOOL)f;
94 @end
95
96 @interface NSView (AppKitSecretsWebBridgeKnowsAbout)
97 - (NSView *)_findLastViewInKeyViewLoop;
98 @end
99
100 @interface NSView (JavaPluginSecrets)
101 - (jobject)pollForAppletInWindow:(NSWindow *)window;
102 @end
103
104 using namespace WebCore;
105
106 NSString *WebPluginBaseURLKey =     @"WebPluginBaseURL";
107 NSString *WebPluginAttributesKey =  @"WebPluginAttributes";
108 NSString *WebPluginContainerKey =   @"WebPluginContainer";
109
110 #define KeyboardUIModeDidChangeNotification @"com.apple.KeyboardUIModeDidChange"
111 #define AppleKeyboardUIMode CFSTR("AppleKeyboardUIMode")
112 #define UniversalAccessDomain CFSTR("com.apple.universalaccess")
113
114 @implementation WebFrameBridge
115
116 - (WebView *)webView
117 {
118     ASSERT([[self _frame]->page()->bridge() isKindOfClass:[WebPageBridge class]]);
119     return [(WebPageBridge *)[self _frame]->page()->bridge() webView];
120 }
121
122 - (void)finishInitializingWithFrameName:(NSString *)name view:(WebFrameView *)view
123 {
124     WebView *webView = [self webView];
125
126     _frame = [[WebFrame alloc] _initWithWebFrameView:view webView:webView coreFrame:m_frame];
127     ++WebBridgeCount;
128
129     [self _frame]->tree()->setName(name);
130     [self _frame]->setSettings([[webView _settings] settings]);
131     [self setTextSizeMultiplier:[webView textSizeMultiplier]];
132 }
133
134 - (id)initMainFrameWithPage:(WebPageBridge *)page frameName:(NSString *)name view:(WebFrameView *)view
135 {
136     // FIXME: Need to clear the WebView pointer in WebEditorClient when the WebView is deallocated.
137     self = [super initMainFrameWithPage:page withEditorClient:new WebEditorClient([page webView])];
138     [self finishInitializingWithFrameName:name view:view];
139     return self;
140 }
141
142 - (id)initSubframeWithOwnerElement:(WebCoreElement *)ownerElement frameName:(NSString *)name view:(WebFrameView *)view
143 {
144     RefPtr<WebEditorClient> editorClient = new WebEditorClient;
145     self = [super initSubframeWithOwnerElement:ownerElement withEditorClient:editorClient.get()];
146     // FIXME: Need to clear the WebView pointer in WebEditorClient when the WebView is deallocated.
147     editorClient->setWebView([self webView]);
148     [self finishInitializingWithFrameName:name view:view];
149     return self;
150 }
151
152 - (void)fini
153 {
154     if (_keyboardUIModeAccessed) {
155         [[NSDistributedNotificationCenter defaultCenter] 
156             removeObserver:self name:KeyboardUIModeDidChangeNotification object:nil];
157         [[NSNotificationCenter defaultCenter] 
158             removeObserver:self name:WebPreferencesChangedNotification object:nil];
159     }
160     ASSERT(_frame == nil);
161     --WebBridgeCount;
162 }
163
164 - (void)dealloc
165 {
166     [lastDashboardRegions release];
167     [_frame release];
168     
169     [self fini];
170     [super dealloc];
171 }
172
173 - (void)finalize
174 {
175     [self fini];
176     [super finalize];
177 }
178
179 - (WebPreferences *)_preferences
180 {
181     return [[self webView] preferences];
182 }
183
184 - (void)_retrieveKeyboardUIModeFromPreferences:(NSNotification *)notification
185 {
186     CFPreferencesAppSynchronize(UniversalAccessDomain);
187
188     Boolean keyExistsAndHasValidFormat;
189     int mode = CFPreferencesGetAppIntegerValue(AppleKeyboardUIMode, UniversalAccessDomain, &keyExistsAndHasValidFormat);
190     
191     // The keyboard access mode is reported by two bits:
192     // Bit 0 is set if feature is on
193     // Bit 1 is set if full keyboard access works for any control, not just text boxes and lists
194     // We require both bits to be on.
195     // I do not know that we would ever get one bit on and the other off since
196     // checking the checkbox in system preferences which is marked as "Turn on full keyboard access"
197     // turns on both bits.
198     _keyboardUIMode = (mode & 0x2) ? WebCoreKeyboardAccessFull : WebCoreKeyboardAccessDefault;
199     
200     // check for tabbing to links
201     if ([[self _preferences] tabsToLinks])
202         _keyboardUIMode = (WebCoreKeyboardUIMode)(_keyboardUIMode | WebCoreKeyboardAccessTabsToLinks);
203 }
204
205 - (WebCoreKeyboardUIMode)keyboardUIMode
206 {
207     if (!_keyboardUIModeAccessed) {
208         _keyboardUIModeAccessed = YES;
209         [self _retrieveKeyboardUIModeFromPreferences:nil];
210         
211         [[NSDistributedNotificationCenter defaultCenter] 
212             addObserver:self selector:@selector(_retrieveKeyboardUIModeFromPreferences:) 
213             name:KeyboardUIModeDidChangeNotification object:nil];
214
215         [[NSNotificationCenter defaultCenter] 
216             addObserver:self selector:@selector(_retrieveKeyboardUIModeFromPreferences:) 
217                    name:WebPreferencesChangedNotification object:nil];
218     }
219     return _keyboardUIMode;
220 }
221
222 - (WebFrame *)webFrame
223 {
224     return _frame;
225 }
226
227 - (WebCoreFrameBridge *)mainFrame
228 {
229     ASSERT(_frame != nil);
230     return [[[self webView] mainFrame] _bridge];
231 }
232
233 - (NSView *)documentView
234 {
235     ASSERT(_frame != nil);
236     return [[_frame frameView] documentView];
237 }
238
239 - (WebCorePageBridge *)createWindowWithURL:(NSURL *)URL
240 {
241     ASSERT(_frame != nil);
242
243     NSMutableURLRequest *request = nil;
244     if (URL != nil && ![URL _web_isEmpty]) {
245         request = [NSMutableURLRequest requestWithURL:URL];
246         [request _web_setHTTPReferrer:m_frame->referrer()];
247     }
248
249     WebView *currentWebView = [self webView];
250     id wd = [currentWebView UIDelegate];
251     WebView *newWebView;
252     if ([wd respondsToSelector:@selector(webView:createWebViewWithRequest:)])
253         newWebView = [wd webView:currentWebView createWebViewWithRequest:request];
254     else
255         newWebView = [[WebDefaultUIDelegate sharedUIDelegate] webView:currentWebView createWebViewWithRequest:request];
256     return [newWebView _pageBridge];
257 }
258
259 - (void)showWindow
260 {
261     WebView *wv = [self webView];
262     [[wv _UIDelegateForwarder] webViewShow:wv];
263 }
264
265 - (BOOL)areToolbarsVisible
266 {
267     ASSERT(_frame != nil);
268     WebView *wv = [self webView];
269     id wd = [wv UIDelegate];
270     if ([wd respondsToSelector:@selector(webViewAreToolbarsVisible:)])
271         return [wd webViewAreToolbarsVisible:wv];
272     return [[WebDefaultUIDelegate sharedUIDelegate] webViewAreToolbarsVisible:wv];
273 }
274
275 - (void)setToolbarsVisible:(BOOL)visible
276 {
277     ASSERT(_frame != nil);
278     WebView *wv = [self webView];
279     [[wv _UIDelegateForwarder] webView:wv setToolbarsVisible:visible];
280 }
281
282 - (void)setScrollbarsVisible:(BOOL)visible
283 {
284     ASSERT(_frame != nil);
285     [[_frame frameView] setAllowsScrolling:visible];
286 }
287
288 - (BOOL)isStatusbarVisible
289 {
290     ASSERT(_frame != nil);
291     WebView *wv = [self webView];
292     id wd = [wv UIDelegate];
293     if ([wd respondsToSelector:@selector(webViewIsStatusBarVisible:)])
294         return [wd webViewIsStatusBarVisible:wv];
295     return [[WebDefaultUIDelegate sharedUIDelegate] webViewIsStatusBarVisible:wv];
296 }
297
298 - (void)setStatusbarVisible:(BOOL)visible
299 {
300     ASSERT(_frame != nil);
301     WebView *wv = [self webView];
302     [[wv _UIDelegateForwarder] webView:wv setStatusBarVisible:visible];
303 }
304
305 - (void)setWindowIsResizable:(BOOL)resizable
306 {
307     ASSERT(_frame != nil);
308     WebView *webView = [self webView];
309     [[webView _UIDelegateForwarder] webView:webView setResizable:resizable];
310 }
311
312 - (NSResponder *)firstResponder
313 {
314     ASSERT(_frame != nil);
315     WebView *webView = [self webView];
316     return [[webView _UIDelegateForwarder] webViewFirstResponder:webView];
317 }
318
319 - (void)makeFirstResponder:(NSResponder *)view
320 {
321     ASSERT(_frame != nil);
322     WebView *webView = [self webView];
323     [webView _pushPerformingProgrammaticFocus];
324     [[webView _UIDelegateForwarder] webView:webView makeFirstResponder:view];
325     [webView _popPerformingProgrammaticFocus];
326 }
327
328 - (void)willMakeFirstResponderForNodeFocus
329 {
330     ASSERT([[[_frame frameView] documentView] isKindOfClass:[WebHTMLView class]]);
331     [(WebHTMLView *)[[_frame frameView] documentView] _willMakeFirstResponderForNodeFocus];
332 }
333
334 - (BOOL)textViewWasFirstResponderAtMouseDownTime:(NSTextView *)textView;
335 {
336     ASSERT(_frame != nil);
337     NSView *documentView = [[_frame frameView] documentView];
338     if (![documentView isKindOfClass:[WebHTMLView class]])
339         return NO;
340     WebHTMLView *webHTMLView = (WebHTMLView *)documentView;
341     return [webHTMLView _textViewWasFirstResponderAtMouseDownTime:textView];
342 }
343
344 - (void)closeWindowSoon
345 {
346     WebView *parentWebView = [self webView];
347
348     // We need to remove the parent WebView from WebViewSets here, before it actually
349     // closes, to make sure that JavaScript code that executes before it closes
350     // can't find it. Otherwise, window.open will select a closed WebView instead of 
351     // opening a new one <rdar://problem/3572585>.
352
353     // We also need to stop the load to prevent further parsing or JavaScript execution
354     // after the window has torn down <rdar://problem/4161660>.
355   
356     // FIXME: This code assumes that the UI delegate will respond to a webViewClose
357     // message by actually closing the WebView. Safari guarantees this behavior, but other apps might not.
358     // This approach is an inherent limitation of not making a close execute immediately
359     // after a call to window.close.
360     
361     [parentWebView setGroupName:nil];
362     [parentWebView stopLoading:self];
363     [parentWebView performSelector:@selector(_closeWindow) withObject:nil afterDelay:0.0];
364 }
365
366 - (NSWindow *)window
367 {
368     ASSERT(_frame != nil);
369     return [[_frame frameView] window];
370 }
371
372 - (void)runJavaScriptAlertPanelWithMessage:(NSString *)message
373 {
374     WebView *wv = [self webView];
375     id wd = [wv UIDelegate];
376     // Check whether delegate implements new version, then whether delegate implements old version. If neither,
377     // fall back to shared delegate's implementation of new version.
378     if ([wd respondsToSelector:@selector(webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:)])
379         [wd webView:wv runJavaScriptAlertPanelWithMessage:message initiatedByFrame:_frame];
380     else if ([wd respondsToSelector:@selector(webView:runJavaScriptAlertPanelWithMessage:)])
381         [wd webView:wv runJavaScriptAlertPanelWithMessage:message];
382     else
383         [[WebDefaultUIDelegate sharedUIDelegate] webView:wv runJavaScriptAlertPanelWithMessage:message initiatedByFrame:_frame];
384 }
385
386 - (BOOL)runJavaScriptConfirmPanelWithMessage:(NSString *)message
387 {
388     WebView *wv = [self webView];
389     id wd = [wv UIDelegate];
390     // Check whether delegate implements new version, then whether delegate implements old version. If neither,
391     // fall back to shared delegate's implementation of new version.
392     if ([wd respondsToSelector:@selector(webView:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:)])
393         return [wd webView:wv runJavaScriptConfirmPanelWithMessage:message initiatedByFrame:_frame];
394     if ([wd respondsToSelector:@selector(webView:runJavaScriptConfirmPanelWithMessage:)])
395         return [wd webView:wv runJavaScriptConfirmPanelWithMessage:message];    
396     return [[WebDefaultUIDelegate sharedUIDelegate] webView:wv runJavaScriptConfirmPanelWithMessage:message initiatedByFrame:_frame];
397 }
398
399 - (BOOL)shouldInterruptJavaScript
400 {
401     WebView *wv = [self webView];
402     id wd = [wv UIDelegate];
403     if ([wd respondsToSelector:@selector(webViewShouldInterruptJavaScript:)])
404         return [wd webViewShouldInterruptJavaScript:wv];
405     return NO;
406 }
407
408 - (BOOL)canRunBeforeUnloadConfirmPanel
409 {
410     WebView *wv = [self webView];
411     id wd = [wv UIDelegate];
412     return [wd respondsToSelector:@selector(webView:runBeforeUnloadConfirmPanelWithMessage:initiatedByFrame:)];
413 }
414
415 - (BOOL)runBeforeUnloadConfirmPanelWithMessage:(NSString *)message
416 {
417     WebView *wv = [self webView];
418     id wd = [wv UIDelegate];
419     if ([wd respondsToSelector:@selector(webView:runBeforeUnloadConfirmPanelWithMessage:initiatedByFrame:)])
420         return [wd webView:wv runBeforeUnloadConfirmPanelWithMessage:message initiatedByFrame:_frame];
421     return YES;
422 }
423
424 - (BOOL)runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText returningText:(NSString **)result
425 {
426     WebView *wv = [self webView];
427     id wd = [wv UIDelegate];
428     // Check whether delegate implements new version, then whether delegate implements old version. If neither,
429     // fall back to shared delegate's implementation of new version.
430     if ([wd respondsToSelector:@selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:)])
431         *result = [wd webView:wv runJavaScriptTextInputPanelWithPrompt:prompt defaultText:defaultText initiatedByFrame:_frame];
432     else if ([wd respondsToSelector:@selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:)])
433         *result = [wd webView:wv runJavaScriptTextInputPanelWithPrompt:prompt defaultText:defaultText];
434     else
435         *result = [[WebDefaultUIDelegate sharedUIDelegate] webView:wv runJavaScriptTextInputPanelWithPrompt:prompt defaultText:defaultText initiatedByFrame:_frame];
436     return *result != nil;
437 }
438
439 - (void)addMessageToConsole:(NSDictionary *)message
440 {
441     WebView *wv = [self webView];
442     id wd = [wv UIDelegate];
443     if ([wd respondsToSelector:@selector(webView:addMessageToConsole:)])
444         [wd webView:wv addMessageToConsole:message];
445 }
446
447 - (void)runOpenPanelForFileButtonWithResultListener:(id<WebCoreOpenPanelResultListener>)resultListener
448 {
449     WebView *wv = [self webView];
450     [[wv _UIDelegateForwarder] webView:wv runOpenPanelForFileButtonWithResultListener:(id<WebOpenPanelResultListener>)resultListener];
451 }
452
453 - (WebDataSource *)dataSource
454 {
455     ASSERT(_frame != nil);
456     WebDataSource *dataSource = [_frame dataSource];
457
458     ASSERT(dataSource != nil);
459
460     return dataSource;
461 }
462
463 - (void)setStatusText:(NSString *)status
464 {
465     ASSERT(_frame != nil);
466     WebView *wv = [self webView];
467     [[wv _UIDelegateForwarder] webView:wv setStatusText:status];
468 }
469
470 - (void)close
471 {
472     [super close];
473     [_frame release];
474     _frame = nil;
475 }
476
477 - (void)activateWindow
478 {
479     [[[self webView] _UIDelegateForwarder] webViewFocus:[self webView]];
480 }
481
482 - (void)deactivateWindow
483 {
484    [[[self webView] _UIDelegateForwarder] webViewUnfocus:[self webView]];
485 }
486
487 - (void)formControlIsBecomingFirstResponder:(NSView *)formControl
488 {
489     // When a form element becomes first responder, its enclosing WebHTMLView might need to
490     // change its focus-displaying state, but isn't otherwise notified.
491     [(WebHTMLView *)[[_frame frameView] documentView] _formControlIsBecomingFirstResponder:formControl];
492 }
493
494 - (void)formControlIsResigningFirstResponder:(NSView *)formControl
495 {
496     // When a form element resigns first responder, its enclosing WebHTMLView might need to
497     // change its focus-displaying state, but isn't otherwise notified.
498     [(WebHTMLView *)[[_frame frameView] documentView] _formControlIsResigningFirstResponder:formControl];
499 }
500
501 - (WebCoreFrameBridge *)createChildFrameNamed:(NSString *)frameName 
502                                       withURL:(NSURL *)URL
503                                      referrer:(const String&)referrer
504                                    ownerElement:(WebCoreElement *)ownerElement
505                               allowsScrolling:(BOOL)allowsScrolling 
506                                   marginWidth:(int)width
507                                  marginHeight:(int)height
508 {
509     bool hideReferrer;
510     if (!m_frame->loader()->canLoad(URL, referrer, hideReferrer))
511         return nil;
512
513     ASSERT(_frame);
514     
515     WebFrameView *childView = [[WebFrameView alloc] initWithFrame:NSMakeRect(0,0,0,0)];
516     [childView setAllowsScrolling:allowsScrolling];
517     WebFrameBridge *newBridge = [[WebFrameBridge alloc] initSubframeWithOwnerElement:ownerElement frameName:frameName view:childView];
518     [_frame _addChild:[newBridge webFrame]];
519     [childView release];
520
521     [childView _setMarginWidth:width];
522     [childView _setMarginHeight:height];
523
524     [newBridge release];
525
526     if (!newBridge)
527         return nil;
528
529     [_frame _loadURL:URL referrer:(hideReferrer ? String() : referrer) intoChild:[newBridge webFrame]];
530
531     return newBridge;
532 }
533
534 - (void)saveDocumentState:(NSArray *)documentState
535 {
536     WebHistoryItem *item = [_frame _itemForSavingDocState];
537     LOG(Loading, "%@: saving form state from to 0x%x", [_frame name], item);
538     if (item)
539         [item setDocumentState:documentState];
540         // You might think we could save the scroll state here too, but unfortunately this
541         // often gets called after WebFrame::_transitionToCommitted has restored the scroll
542         // position of the next document.
543 }
544
545 - (NSArray *)documentState
546 {
547     LOG(Loading, "%@: restoring form state from item 0x%x", [_frame name], [_frame _itemForRestoringDocState]);
548     return [[_frame _itemForRestoringDocState] documentState];
549 }
550
551 - (NSString *)userAgentForURL:(NSURL *)URL
552 {
553     return [[self webView] userAgentForURL:URL];
554 }
555
556 - (BOOL)inNextKeyViewOutsideWebFrameViews
557 {
558     return _inNextKeyViewOutsideWebFrameViews;
559 }
560
561 - (NSView *)_nextKeyViewOutsideWebFrameViewsWithValidityCheck:(BOOL)mustBeValid
562 {
563     // We can get here in unusual situations such as the one listed in 4451831, so we
564     // return nil to avoid an infinite recursion.
565     if (_inNextKeyViewOutsideWebFrameViews)
566         return nil;
567     
568     _inNextKeyViewOutsideWebFrameViews = YES;
569     WebView *webView = [self webView];
570     // Do not ask webView for its next key view, but rather, ask it for 
571     // the next key view of the last view in its key view loop.
572     // Doing so gives us the correct answer as calculated by AppKit, 
573     // and makes HTML views behave like other views.
574     NSView *lastViewInLoop = [webView _findLastViewInKeyViewLoop];
575     NSView *nextKeyView = mustBeValid ? [lastViewInLoop nextValidKeyView] : [lastViewInLoop nextKeyView];
576     _inNextKeyViewOutsideWebFrameViews = NO;
577     return nextKeyView;
578 }
579
580 - (NSView *)nextKeyViewOutsideWebFrameViews
581 {
582     return [self _nextKeyViewOutsideWebFrameViewsWithValidityCheck:NO];
583 }
584
585 - (NSView *)nextValidKeyViewOutsideWebFrameViews
586 {
587     return [self _nextKeyViewOutsideWebFrameViewsWithValidityCheck:YES];
588 }
589
590 - (NSView *)previousKeyViewOutsideWebFrameViews
591 {
592     return [[self webView] previousKeyView];
593 }
594
595 - (void)setNeedsReapplyStyles
596 {
597     NSView <WebDocumentView> *view = [[_frame frameView] documentView];
598     if ([view isKindOfClass:[WebHTMLView class]]) {
599         [(WebHTMLView *)view setNeedsToApplyStyles:YES];
600         [view setNeedsLayout:YES];
601         [view setNeedsDisplay:YES];
602     }
603 }
604
605 - (NSView *)pluginViewWithPackage:(WebPluginPackage *)pluginPackage
606                    attributeNames:(NSArray *)attributeNames
607                   attributeValues:(NSArray *)attributeValues
608                           baseURL:(NSURL *)baseURL
609                        DOMElement:(DOMElement *)element
610                      loadManually:(BOOL)loadManually
611 {
612     WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
613     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
614         
615     WebPluginController *pluginController = [docView _pluginController];
616     
617     // Store attributes in a dictionary so they can be passed to WebPlugins.
618     NSMutableDictionary *attributes = [[NSMutableDictionary alloc] initWithObjects:attributeValues forKeys:attributeNames];
619     
620     [pluginPackage load];
621     Class viewFactory = [pluginPackage viewFactory];
622     
623     NSView *view = nil;
624     NSDictionary *arguments = nil;
625     
626     if ([viewFactory respondsToSelector:@selector(plugInViewWithArguments:)]) {
627         arguments = [NSDictionary dictionaryWithObjectsAndKeys:
628             baseURL, WebPlugInBaseURLKey,
629             attributes, WebPlugInAttributesKey,
630             pluginController, WebPlugInContainerKey,
631             [NSNumber numberWithInt:loadManually ? WebPlugInModeFull : WebPlugInModeEmbed], WebPlugInModeKey,
632             [NSNumber numberWithBool:!loadManually], WebPlugInShouldLoadMainResourceKey,
633             element, WebPlugInContainingElementKey,
634             nil];
635         LOG(Plugins, "arguments:\n%@", arguments);
636     } else if ([viewFactory respondsToSelector:@selector(pluginViewWithArguments:)]) {
637         arguments = [NSDictionary dictionaryWithObjectsAndKeys:
638             baseURL, WebPluginBaseURLKey,
639             attributes, WebPluginAttributesKey,
640             pluginController, WebPluginContainerKey,
641             element, WebPlugInContainingElementKey,
642             nil];
643         LOG(Plugins, "arguments:\n%@", arguments);
644     }
645
646     view = [WebPluginController plugInViewWithArguments:arguments fromPluginPackage:pluginPackage];
647     
648     [attributes release];
649     return view;
650 }
651
652 - (NSString *)valueForKey:(NSString *)key keys:(NSArray *)keys values:(NSArray *)values
653 {
654     unsigned count = [keys count];
655     unsigned i;
656     for (i = 0; i < count; i++)
657         if ([[keys objectAtIndex:i] _webkit_isCaseInsensitiveEqualToString:key])
658             return [values objectAtIndex:i];
659     return nil;
660 }
661
662 - (NSView *)viewForPluginWithURL:(NSURL *)URL
663                   attributeNames:(NSArray *)attributeNames
664                  attributeValues:(NSArray *)attributeValues
665                         MIMEType:(NSString *)MIMEType
666                       DOMElement:(DOMElement *)element
667                     loadManually:(BOOL)loadManually
668 {
669     bool hideReferrer;
670     if (!m_frame->loader()->canLoad(URL, m_frame->referrer(), hideReferrer))
671         return nil;
672
673     ASSERT([attributeNames count] == [attributeValues count]);
674
675     WebBasePluginPackage *pluginPackage = nil;
676     NSView *view = nil;
677     int errorCode = 0;
678
679     WebView *wv = [self webView];
680     id wd = [wv UIDelegate];
681
682     if ([wd respondsToSelector:@selector(webView:plugInViewWithArguments:)]) {
683         NSMutableDictionary *attributes = [[NSMutableDictionary alloc] initWithObjects:attributeValues forKeys:attributeNames];
684         NSDictionary *arguments = [NSDictionary dictionaryWithObjectsAndKeys:
685             attributes, WebPlugInAttributesKey,
686             [NSNumber numberWithInt:loadManually ? WebPlugInModeFull : WebPlugInModeEmbed], WebPlugInModeKey,
687             URL, WebPlugInBaseURLKey, // URL might be nil, so add it last
688             [NSNumber numberWithBool:!loadManually], WebPlugInShouldLoadMainResourceKey,
689             element, WebPlugInContainingElementKey,
690             nil];
691         [attributes release];
692         view = [wd webView:wv plugInViewWithArguments:arguments];
693         if (view)
694             return view;
695     }
696
697     if ([MIMEType length] != 0)
698         pluginPackage = [[self webView] _pluginForMIMEType:MIMEType];
699     else
700         MIMEType = nil;
701     
702     NSString *extension = [[URL path] pathExtension];
703     if (!pluginPackage && [extension length] != 0) {
704         pluginPackage = [[self webView] _pluginForExtension:extension];
705         if (pluginPackage) {
706             NSString *newMIMEType = [pluginPackage MIMETypeForExtension:extension];
707             if ([newMIMEType length] != 0)
708                 MIMEType = newMIMEType;
709         }
710     }
711
712     NSURL *baseURL = [self baseURL];
713     if (pluginPackage) {
714         if ([pluginPackage isKindOfClass:[WebPluginPackage class]]) {
715             view = [self pluginViewWithPackage:(WebPluginPackage *)pluginPackage
716                                 attributeNames:attributeNames
717                                attributeValues:attributeValues
718                                        baseURL:baseURL
719                                     DOMElement:element
720                                   loadManually:loadManually];
721         } else if ([pluginPackage isKindOfClass:[WebNetscapePluginPackage class]]) {
722             WebNetscapePluginEmbeddedView *embeddedView = [[[WebNetscapePluginEmbeddedView alloc] initWithFrame:NSZeroRect
723                                                                   plugin:(WebNetscapePluginPackage *)pluginPackage
724                                                                      URL:URL
725                                                                  baseURL:baseURL
726                                                                 MIMEType:MIMEType
727                                                            attributeKeys:attributeNames
728                                                          attributeValues:attributeValues
729                                                             loadManually:loadManually
730                                                               DOMElement:element] autorelease];
731             view = embeddedView;
732             [_frame _addPlugInView:embeddedView];
733         } else
734             ASSERT_NOT_REACHED();
735     } else
736         errorCode = WebKitErrorCannotFindPlugIn;
737
738     if (!errorCode && !view)
739         errorCode = WebKitErrorCannotLoadPlugIn;
740
741     if (errorCode) {
742         NSString *pluginPage = [self valueForKey:@"pluginspage" keys:attributeNames values:attributeValues];
743         NSURL *pluginPageURL = pluginPage != nil ? [self URLWithAttributeString:pluginPage] : nil;
744         NSError *error = [[NSError alloc] _initWithPluginErrorCode:errorCode
745                                                         contentURL:URL
746                                                      pluginPageURL:pluginPageURL
747                                                         pluginName:[pluginPackage name]
748                                                           MIMEType:MIMEType];
749         WebNullPluginView *nullView = [[[WebNullPluginView alloc] initWithFrame:NSZeroRect error:error] autorelease];
750         [_frame _addPlugInView:nullView];
751         view = nullView;
752         [error release];
753     }
754     
755     ASSERT(view);
756     return view;
757 }
758
759 - (void)redirectDataToPlugin:(NSView *)pluginView
760 {
761     WebHTMLRepresentation *representation = (WebHTMLRepresentation *)[[_frame dataSource] representation];
762
763     if ([pluginView isKindOfClass:[WebNetscapePluginEmbeddedView class]])
764         [representation _redirectDataToManualLoader:(WebNetscapePluginEmbeddedView *)pluginView forPluginView:pluginView];
765     else {
766         WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
767         ASSERT([docView isKindOfClass:[WebHTMLView class]]);
768         
769         WebPluginController *pluginController = [docView _pluginController];
770         [representation _redirectDataToManualLoader:pluginController forPluginView:pluginView];
771     }
772 }
773
774 - (NSView *)viewForJavaAppletWithFrame:(NSRect)theFrame
775                         attributeNames:(NSArray *)attributeNames
776                        attributeValues:(NSArray *)attributeValues
777                                baseURL:(NSURL *)baseURL
778                             DOMElement:(DOMElement *)element
779 {
780     NSString *MIMEType = @"application/x-java-applet";
781     WebBasePluginPackage *pluginPackage;
782     NSView *view = nil;
783     
784     pluginPackage = [[self webView] _pluginForMIMEType:MIMEType];
785
786     if (pluginPackage) {
787         if ([pluginPackage isKindOfClass:[WebPluginPackage class]]) {
788             // For some reason, the Java plug-in requires that we pass the dimension of the plug-in as attributes.
789             NSMutableArray *names = [attributeNames mutableCopy];
790             NSMutableArray *values = [attributeValues mutableCopy];
791             if ([self valueForKey:@"width" keys:attributeNames values:attributeValues] == nil) {
792                 [names addObject:@"width"];
793                 [values addObject:[NSString stringWithFormat:@"%d", (int)theFrame.size.width]];
794             }
795             if ([self valueForKey:@"height" keys:attributeNames values:attributeValues] == nil) {
796                 [names addObject:@"height"];
797                 [values addObject:[NSString stringWithFormat:@"%d", (int)theFrame.size.height]];
798             }
799             view = [self pluginViewWithPackage:(WebPluginPackage *)pluginPackage
800                                 attributeNames:names
801                                attributeValues:values
802                                        baseURL:baseURL
803                                     DOMElement:element
804                                   loadManually:NO];
805             [names release];
806             [values release];
807         } else if ([pluginPackage isKindOfClass:[WebNetscapePluginPackage class]]) {
808             view = [[[WebNetscapePluginEmbeddedView alloc] initWithFrame:theFrame
809                                                                   plugin:(WebNetscapePluginPackage *)pluginPackage
810                                                                      URL:nil
811                                                                  baseURL:baseURL
812                                                                 MIMEType:MIMEType
813                                                            attributeKeys:attributeNames
814                                                          attributeValues:attributeValues
815                                                             loadManually:NO
816                                                               DOMElement:element] autorelease];
817         } else {
818             ASSERT_NOT_REACHED();
819         }
820     }
821
822     if (!view) {
823         NSError *error = [[NSError alloc] _initWithPluginErrorCode:WebKitErrorJavaUnavailable
824                                                         contentURL:nil
825                                                      pluginPageURL:nil
826                                                         pluginName:[pluginPackage name]
827                                                           MIMEType:MIMEType];
828         view = [[[WebNullPluginView alloc] initWithFrame:theFrame error:error] autorelease];
829         [error release];
830     }
831
832     ASSERT(view);
833
834     return view;
835 }
836
837 #ifndef NDEBUG
838 static BOOL loggedObjectCacheSize = NO;
839 #endif
840
841 -(int)getObjectCacheSize
842 {
843     vm_size_t memSize = WebSystemMainMemory();
844     int cacheSize = [[self _preferences] _objectCacheSize];
845     int multiplier = 1;
846     
847     // 2GB and greater will be 128mb.  1gb and greater will be 64mb.
848     // Otherwise just use 32mb.
849     if (memSize >= (unsigned)(2048 * 1024 * 1024)) 
850         multiplier = 4;
851     else if (memSize >= 1024 * 1024 * 1024)
852         multiplier = 2;
853
854 #ifndef NDEBUG
855     if (!loggedObjectCacheSize){
856         LOG(CacheSizes, "Object cache size set to %d bytes.", cacheSize * multiplier);
857         loggedObjectCacheSize = YES;
858     }
859 #endif
860
861     return cacheSize * multiplier;
862 }
863
864 - (ObjectElementType)determineObjectFromMIMEType:(NSString*)MIMEType URL:(NSURL*)URL
865 {
866     if ([MIMEType length] == 0) {
867         // Try to guess the MIME type based off the extension.
868         NSString *extension = [[URL path] pathExtension];
869         if ([extension length] > 0) {
870             MIMEType = WKGetMIMETypeForExtension(extension);
871             if ([MIMEType length] == 0 && [[self webView] _pluginForExtension:extension])
872                 // If no MIME type is specified, use a plug-in if we have one that can handle the extension.
873                 return ObjectElementPlugin;
874         }
875     }
876
877     if ([MIMEType length] == 0)
878         return ObjectElementFrame; // Go ahead and hope that we can display the content.
879
880     if ([[WebCoreFrameBridge supportedImageMIMETypes] containsObject:MIMEType])
881         return ObjectElementFrame;
882
883     if ([[self webView] _isMIMETypeRegisteredAsPlugin:MIMEType])
884         return ObjectElementPlugin;
885
886     if ([WebFrameView _viewClassForMIMEType:MIMEType])
887         return ObjectElementFrame;
888     
889     return ObjectElementNone;
890 }
891
892 - (NSString *)MIMETypeForPath:(NSString *)path
893 {
894     ASSERT(path);
895     NSString *extension = [path pathExtension];
896     NSString *type = WKGetMIMETypeForExtension(extension);
897     return [type length] == 0 ? (NSString *)@"application/octet-stream" : type;
898 }
899
900 - (void)allowDHTMLDrag:(BOOL *)flagDHTML UADrag:(BOOL *)flagUA
901 {
902     WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
903     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
904     unsigned int mask = [docView _delegateDragSourceActionMask];
905     *flagDHTML = (mask & WebDragSourceActionDHTML) != 0;
906     *flagUA = ((mask & WebDragSourceActionImage) || (mask & WebDragSourceActionLink) || (mask & WebDragSourceActionSelection));
907 }
908
909 - (BOOL)startDraggingImage:(NSImage *)dragImage at:(NSPoint)dragLoc operation:(NSDragOperation)op
910     event:(NSEvent *)event sourceIsDHTML:(BOOL)flag DHTMLWroteData:(BOOL)dhtmlWroteData
911 {
912     WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
913     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
914     [docView _setInitiatedDrag:YES];
915     return [docView _startDraggingImage:dragImage at:dragLoc operation:op event:event
916         sourceIsDHTML:flag DHTMLWroteData:dhtmlWroteData];
917 }
918
919 - (BOOL)mayStartDragAtEventLocation:(NSPoint)location
920 {
921     WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
922     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
923     return [docView _mayStartDragAtEventLocation:location];
924 }
925
926 - (BOOL)selectWordBeforeMenuEvent
927 {
928     return [[self webView] _selectWordBeforeMenuEvent];
929 }
930
931 - (int)historyLength
932 {
933     return [[[self webView] backForwardList] backListCount] + 1;
934 }
935
936 - (BOOL)canGoBackOrForward:(int)distance
937 {
938     if (distance == 0)
939         return YES;
940     if (distance > 0 && distance <= [[[self webView] backForwardList] forwardListCount])
941         return YES;
942     if (distance < 0 && -distance <= [[[self webView] backForwardList] backListCount])
943         return YES;
944     return NO;
945 }
946
947 - (void)goBackOrForward:(int)distance
948 {
949     if (distance == 0)
950         return;
951     WebView *webView = [self webView];
952     WebBackForwardList *list = [webView backForwardList];
953     WebHistoryItem *item = [list itemAtIndex:distance];
954     if (!item) {
955         if (distance > 0) {
956             int forwardListCount = [list forwardListCount];
957             if (forwardListCount > 0) {
958                 item = [list itemAtIndex:forwardListCount];
959             }
960         } else {
961             int backListCount = [list forwardListCount];
962             if (backListCount > 0) {
963                 item = [list itemAtIndex:-backListCount];
964             }
965         }
966     }
967     if (item) {
968         [webView goToBackForwardItem:item];
969     }
970 }
971
972 - (NSURL*)historyURL:(int)distance
973 {
974     WebView *webView = [self webView];
975     WebBackForwardList *list = [webView backForwardList];
976     WebHistoryItem *item = [list itemAtIndex:distance];
977     if (!item) {
978         if (distance > 0) {
979             int forwardListCount = [list forwardListCount];
980             if (forwardListCount > 0)
981                 item = [list itemAtIndex:forwardListCount];
982         } else {
983             int backListCount = [list forwardListCount];
984             if (backListCount > 0)
985                 item = [list itemAtIndex:-backListCount];
986         }
987     }
988     if (item)
989         return [item URL];
990     
991     return nil;
992 }
993
994 static id <WebFormDelegate> formDelegate(WebFrameBridge *self)
995 {
996     ASSERT(self->_frame != nil);
997     return [[self->_frame webView] _formDelegate];
998 }
999
1000 #define FormDelegateLog(ctrl)  LOG(FormDelegate, "control=%@", ctrl)
1001
1002 - (void)textFieldDidBeginEditing:(DOMHTMLInputElement *)element
1003 {
1004     FormDelegateLog(element);
1005     [formDelegate(self) textFieldDidBeginEditing:element inFrame:_frame];
1006 }
1007
1008 - (void)textFieldDidEndEditing:(DOMHTMLInputElement *)element
1009 {
1010     FormDelegateLog(element);
1011     [formDelegate(self) textFieldDidEndEditing:element inFrame:_frame];
1012 }
1013
1014 - (void)textDidChangeInTextField:(DOMHTMLInputElement *)element
1015 {
1016     FormDelegateLog(element);
1017     [formDelegate(self) textDidChangeInTextField:(DOMHTMLInputElement *)element inFrame:_frame];
1018 }
1019
1020 - (void)textDidChangeInTextArea:(DOMHTMLTextAreaElement *)element
1021 {
1022     FormDelegateLog(element);
1023     [formDelegate(self) textDidChangeInTextArea:element inFrame:_frame];
1024 }
1025
1026 - (BOOL)textField:(DOMHTMLInputElement *)element doCommandBySelector:(SEL)commandSelector
1027 {
1028     FormDelegateLog(element);
1029     return [formDelegate(self) textField:element doCommandBySelector:commandSelector inFrame:_frame];
1030 }
1031
1032 - (BOOL)textField:(DOMHTMLInputElement *)element shouldHandleEvent:(NSEvent *)event
1033 {
1034     FormDelegateLog(element);
1035     return [formDelegate(self) textField:element shouldHandleEvent:event inFrame:_frame];
1036 }
1037
1038 - (void)setHasBorder:(BOOL)hasBorder
1039 {
1040     [[_frame frameView] _setHasBorder:hasBorder];
1041 }
1042
1043 - (void)print
1044 {
1045     id wd = [[self webView] UIDelegate];    
1046     if ([wd respondsToSelector:@selector(webView:printFrameView:)])
1047         [wd webView:[self webView] printFrameView:[_frame frameView]];
1048     else
1049         [[WebDefaultUIDelegate sharedUIDelegate] webView:[self webView] printFrameView:[_frame frameView]];
1050 }
1051
1052 - (jobject)getAppletInView:(NSView *)view
1053 {
1054     if ([view respondsToSelector:@selector(webPlugInGetApplet)])
1055         return [view webPlugInGetApplet];
1056     return [self pollForAppletInView:view];
1057 }
1058
1059 // NOTE: pollForAppletInView: will block until the block is ready to use, or
1060 // until a timeout is exceeded.  It will return nil if the timeout is
1061 // exceeded.
1062 // Deprecated, use getAppletInView:.
1063 - (jobject)pollForAppletInView:(NSView *)view
1064 {
1065     if ([view respondsToSelector:@selector(pollForAppletInWindow:)])
1066         // The Java VM needs the containing window of the view to
1067         // initialize. The view may not yet be in the window's view 
1068         // hierarchy, so we have to pass the window when requesting
1069         // the applet.
1070         return [view pollForAppletInWindow:[[self webView] window]];
1071     return 0;
1072 }
1073
1074 - (void)respondToChangedContents
1075 {
1076     NSView <WebDocumentView> *view = [[_frame frameView] documentView];
1077     if ([view isKindOfClass:[WebHTMLView class]])
1078         [(WebHTMLView *)view _updateFontPanel];
1079     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewDidChangeNotification object:[self webView]];
1080 }
1081
1082 - (void)respondToChangedSelection
1083 {
1084     NSView <WebDocumentView> *view = [[_frame frameView] documentView];
1085     if ([view isKindOfClass:[WebHTMLView class]])
1086         [(WebHTMLView *)view _selectionChanged];
1087     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewDidChangeSelectionNotification object:[self webView]];
1088 }
1089
1090 - (NSUndoManager *)undoManager
1091 {
1092     return [[self webView] undoManager];
1093 }
1094
1095 - (void)issueCutCommand
1096 {
1097     NSView* documentView = [[_frame frameView] documentView];
1098     if ([documentView isKindOfClass:[WebHTMLView class]])
1099         [(WebHTMLView*)documentView cut:nil];
1100 }
1101
1102 - (void)issueCopyCommand
1103 {
1104     NSView* documentView = [[_frame frameView] documentView];
1105     if ([documentView isKindOfClass:[WebHTMLView class]])
1106         [(WebHTMLView*)documentView copy:nil];
1107 }
1108
1109 - (void)issuePasteCommand
1110 {
1111     NSView* documentView = [[_frame frameView] documentView];
1112     if ([documentView isKindOfClass:[WebHTMLView class]])
1113         [(WebHTMLView*)documentView paste:nil];
1114 }
1115
1116 - (void)issuePasteAndMatchStyleCommand
1117 {
1118     NSView <WebDocumentView> *documentView = [[_frame frameView] documentView];
1119     if ([documentView isKindOfClass:[WebHTMLView class]])
1120         [(WebHTMLView*)documentView pasteAsPlainText:nil];
1121 }
1122
1123 - (void)issueTransposeCommand
1124 {
1125     NSView <WebDocumentView> *view = [[_frame frameView] documentView];
1126     if ([view isKindOfClass:[WebHTMLView class]])
1127         [(WebHTMLView *)view transpose:nil];
1128 }
1129
1130 - (void)setIsSelected:(BOOL)isSelected forView:(NSView *)view
1131 {
1132     if ([view respondsToSelector:@selector(webPlugInSetIsSelected:)])
1133         [view webPlugInSetIsSelected:isSelected];
1134     else if ([view respondsToSelector:@selector(setIsSelected:)])
1135         [view setIsSelected:isSelected];
1136 }
1137
1138 - (NSString *)overrideMediaType
1139 {
1140     return [[self webView] mediaStyle];
1141 }
1142
1143 - (BOOL)isEditable
1144 {
1145     return [[self webView] isEditable];
1146 }
1147
1148 - (BOOL)shouldChangeSelectedDOMRange:(DOMRange *)currentRange toDOMRange:(DOMRange *)proposedRange affinity:(WebCore::EAffinity)selectionAffinity stillSelecting:(BOOL)flag
1149 {
1150     return [[self webView] _shouldChangeSelectedDOMRange:currentRange toDOMRange:proposedRange affinity:kit(selectionAffinity) stillSelecting:flag];
1151 }
1152
1153 - (BOOL)shouldDeleteSelectedDOMRange:(DOMRange *)range
1154 {
1155     WebView *webView = [self webView];
1156     return [[webView _editingDelegateForwarder] webView:webView shouldDeleteDOMRange:range];
1157 }
1158
1159 - (BOOL)shouldBeginEditing:(DOMRange *)range
1160 {
1161     return [[self webView] _shouldBeginEditingInDOMRange:range];
1162 }
1163
1164 - (BOOL)shouldEndEditing:(DOMRange *)range
1165 {
1166     return [[self webView] _shouldEndEditingInDOMRange:range];
1167 }
1168
1169 - (void)didBeginEditing
1170 {
1171     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewDidBeginEditingNotification object:[_frame webView]];
1172 }
1173
1174 - (void)didEndEditing
1175 {
1176     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewDidEndEditingNotification object:[_frame webView]];
1177 }
1178
1179 - (void)windowObjectCleared
1180 {
1181     WebView *wv = [self webView];
1182     [[wv _frameLoadDelegateForwarder] webView:wv windowScriptObjectAvailable:m_frame->windowScriptObject()];
1183     if ([wv scriptDebugDelegate] || [WebScriptDebugServer listenerCount]) {
1184         [_frame _detachScriptDebugger]; // FIXME: remove this once <rdar://problem/4608404> is fixed
1185         [_frame _attachScriptDebugger];
1186     }
1187 }
1188
1189 - (BOOL)_compareDashboardRegions:(NSDictionary *)regions
1190 {
1191     return [lastDashboardRegions isEqualToDictionary:regions];
1192 }
1193
1194 - (void)dashboardRegionsChanged:(NSMutableDictionary *)regions
1195 {
1196     WebView *wv = [self webView];
1197     id wd = [wv UIDelegate];
1198     
1199     [wv _addScrollerDashboardRegions:regions];
1200     
1201     if (![self _compareDashboardRegions:regions]) {
1202         if ([wd respondsToSelector:@selector(webView:dashboardRegionsChanged:)]) {
1203             [wd webView:wv dashboardRegionsChanged:regions];
1204             [lastDashboardRegions release];
1205             lastDashboardRegions = [regions retain];
1206         }
1207     }
1208 }
1209
1210 - (void)willPopupMenu:(NSMenu *)menu
1211 {
1212     WebView *wv = [self webView];
1213     id wd = [wv UIDelegate];
1214         
1215     if ([wd respondsToSelector:@selector(webView:willPopupMenu:)])
1216         [wd webView:wv willPopupMenu:menu];
1217 }
1218
1219 - (NSRect)customHighlightRect:(NSString*)type forLine:(NSRect)lineRect
1220 {
1221     ASSERT(_frame != nil);
1222     NSView *documentView = [[_frame frameView] documentView];
1223     if (![documentView isKindOfClass:[WebHTMLView class]])
1224         return NSZeroRect;
1225
1226     WebHTMLView *webHTMLView = (WebHTMLView *)documentView;
1227     id<WebHTMLHighlighter> highlighter = [webHTMLView _highlighterForType:type];
1228     return [highlighter highlightRectForLine:lineRect];
1229 }
1230
1231 - (void)paintCustomHighlight:(NSString*)type forBox:(NSRect)boxRect onLine:(NSRect)lineRect behindText:(BOOL)text
1232                   entireLine:(BOOL)line
1233 {
1234     ASSERT(_frame != nil);
1235     NSView *documentView = [[_frame frameView] documentView];
1236     if (![documentView isKindOfClass:[WebHTMLView class]])
1237         return;
1238
1239     WebHTMLView *webHTMLView = (WebHTMLView *)documentView;
1240     id<WebHTMLHighlighter> highlighter = [webHTMLView _highlighterForType:type];
1241     [highlighter paintHighlightForBox:boxRect onLine:lineRect behindText:text entireLine:line];
1242 }
1243
1244 - (NSString *)nameForUndoAction:(WebUndoAction)undoAction
1245 {
1246     switch (undoAction) {
1247         case WebUndoActionUnspecified: return nil;
1248         case WebUndoActionSetColor: return UI_STRING_KEY("Set Color", "Set Color (Undo action name)", "Undo action name");
1249         case WebUndoActionSetBackgroundColor: return UI_STRING_KEY("Set Background Color", "Set Background Color (Undo action name)", "Undo action name");
1250         case WebUndoActionTurnOffKerning: return UI_STRING_KEY("Turn Off Kerning", "Turn Off Kerning (Undo action name)", "Undo action name");
1251         case WebUndoActionTightenKerning: return UI_STRING_KEY("Tighten Kerning", "Tighten Kerning (Undo action name)", "Undo action name");
1252         case WebUndoActionLoosenKerning: return UI_STRING_KEY("Loosen Kerning", "Loosen Kerning (Undo action name)", "Undo action name");
1253         case WebUndoActionUseStandardKerning: return UI_STRING_KEY("Use Standard Kerning", "Use Standard Kerning (Undo action name)", "Undo action name");
1254         case WebUndoActionTurnOffLigatures: return UI_STRING_KEY("Turn Off Ligatures", "Turn Off Ligatures (Undo action name)", "Undo action name");
1255         case WebUndoActionUseStandardLigatures: return UI_STRING_KEY("Use Standard Ligatures", "Use Standard Ligatures (Undo action name)", "Undo action name");
1256         case WebUndoActionUseAllLigatures: return UI_STRING_KEY("Use All Ligatures", "Use All Ligatures (Undo action name)", "Undo action name");
1257         case WebUndoActionRaiseBaseline: return UI_STRING_KEY("Raise Baseline", "Raise Baseline (Undo action name)", "Undo action name");
1258         case WebUndoActionLowerBaseline: return UI_STRING_KEY("Lower Baseline", "Lower Baseline (Undo action name)", "Undo action name");
1259         case WebUndoActionSetTraditionalCharacterShape: return UI_STRING_KEY("Set Traditional Character Shape", "Set Traditional Character Shape (Undo action name)", "Undo action name");
1260         case WebUndoActionSetFont: return UI_STRING_KEY("Set Font", "Set Font (Undo action name)", "Undo action name");
1261         case WebUndoActionChangeAttributes: return UI_STRING_KEY("Change Attributes", "Change Attributes (Undo action name)", "Undo action name");
1262         case WebUndoActionAlignLeft: return UI_STRING_KEY("Align Left", "Align Left (Undo action name)", "Undo action name");
1263         case WebUndoActionAlignRight: return UI_STRING_KEY("Align Right", "Align Right (Undo action name)", "Undo action name");
1264         case WebUndoActionCenter: return UI_STRING_KEY("Center", "Center (Undo action name)", "Undo action name");
1265         case WebUndoActionJustify: return UI_STRING_KEY("Justify", "Justify (Undo action name)", "Undo action name");
1266         case WebUndoActionSetWritingDirection: return UI_STRING_KEY("Set Writing Direction", "Set Writing Direction (Undo action name)", "Undo action name");
1267         case WebUndoActionSubscript: return UI_STRING_KEY("Subscript", "Subscript (Undo action name)", "Undo action name");
1268         case WebUndoActionSuperscript: return UI_STRING_KEY("Superscript", "Superscript (Undo action name)", "Undo action name");
1269         case WebUndoActionUnderline: return UI_STRING_KEY("Underline", "Underline (Undo action name)", "Undo action name");
1270         case WebUndoActionOutline: return UI_STRING_KEY("Outline", "Outline (Undo action name)", "Undo action name");
1271         case WebUndoActionUnscript: return UI_STRING_KEY("Unscript", "Unscript (Undo action name)", "Undo action name");
1272         case WebUndoActionDrag: return UI_STRING_KEY("Drag", "Drag (Undo action name)", "Undo action name");
1273         case WebUndoActionCut: return UI_STRING_KEY("Cut", "Cut (Undo action name)", "Undo action name");
1274         case WebUndoActionPaste: return UI_STRING_KEY("Paste", "Paste (Undo action name)", "Undo action name");
1275         case WebUndoActionPasteFont: return UI_STRING_KEY("Paste Font", "Paste Font (Undo action name)", "Undo action name");
1276         case WebUndoActionPasteRuler: return UI_STRING_KEY("Paste Ruler", "Paste Ruler (Undo action name)", "Undo action name");
1277         case WebUndoActionTyping: return UI_STRING_KEY("Typing", "Typing (Undo action name)", "Undo action name");
1278         case WebUndoActionCreateLink: return UI_STRING_KEY("Create Link", "Create Link (Undo action name)", "Undo action name");
1279         case WebUndoActionUnlink: return UI_STRING_KEY("Unlink", "Unlink (Undo action name)", "Undo action name");
1280         case WebUndoActionInsertList: return UI_STRING_KEY("Insert List", "Insert List (Undo action name)", "Undo action name");
1281         case WebUndoActionFormatBlock: return UI_STRING_KEY("Formatting", "Format Block (Undo action name)", "Undo action name");
1282         case WebUndoActionIndent: return UI_STRING_KEY("Indent", "Indent (Undo action name)", "Undo action name");
1283         case WebUndoActionOutdent: return UI_STRING_KEY("Outdent", "Outdent (Undo action name)", "Undo action name");
1284     }
1285     return nil;
1286 }
1287
1288 - (NSString*)imageTitleForFilename:(NSString*)filename size:(NSSize)size
1289 {
1290     return [NSString stringWithFormat:UI_STRING("%@ %.0f×%.0f pixels", "window title for a standalone image (uses multiplication symbol, not x)"), filename, size.width, size.height];
1291 }
1292
1293 @end