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