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