Remove some dead code.
[WebKit-https.git] / Source / WebKit / mac / WebView / WebFrame.mm
1 /*
2  * Copyright (C) 2005, 2006, 2007, 2008 Apple 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 "WebFrameInternal.h"
30
31 #import "DOMCSSStyleDeclarationInternal.h"
32 #import "DOMDocumentFragmentInternal.h"
33 #import "DOMDocumentInternal.h"
34 #import "DOMElementInternal.h"
35 #import "DOMHTMLElementInternal.h"
36 #import "DOMNodeInternal.h"
37 #import "DOMRangeInternal.h"
38 #import "WebArchiveInternal.h"
39 #import "WebChromeClient.h"
40 #import "WebDataSourceInternal.h"
41 #import "WebDocumentLoaderMac.h"
42 #import "WebDynamicScrollBarsView.h"
43 #import "WebFrameLoaderClient.h"
44 #import "WebFrameViewInternal.h"
45 #import "WebHTMLView.h"
46 #import "WebHTMLViewInternal.h"
47 #import "WebKitStatisticsPrivate.h"
48 #import "WebKitVersionChecks.h"
49 #import "WebNSObjectExtras.h"
50 #import "WebNSURLExtras.h"
51 #import "WebScriptDebugger.h"
52 #import "WebScriptWorldInternal.h"
53 #import "WebViewInternal.h"
54 #import <JavaScriptCore/APICast.h>
55 #import <WebCore/AXObjectCache.h>
56 #import <WebCore/AccessibilityObject.h>
57 #import <WebCore/AnimationController.h>
58 #import <WebCore/CSSMutableStyleDeclaration.h>
59 #import <WebCore/CachedResourceLoader.h>
60 #import <WebCore/Chrome.h>
61 #import <WebCore/ColorMac.h>
62 #import <WebCore/DOMImplementation.h>
63 #import <WebCore/DocumentFragment.h>
64 #import <WebCore/DocumentLoader.h>
65 #import <WebCore/DocumentMarkerController.h>
66 #import <WebCore/EventHandler.h>
67 #import <WebCore/EventNames.h>
68 #import <WebCore/Frame.h>
69 #import <WebCore/FrameLoader.h>
70 #import <WebCore/FrameLoaderStateMachine.h>
71 #import <WebCore/FrameTree.h>
72 #import <WebCore/GraphicsContext.h>
73 #import <WebCore/HTMLFrameOwnerElement.h>
74 #import <WebCore/HistoryItem.h>
75 #import <WebCore/HitTestResult.h>
76 #import <WebCore/LegacyWebArchive.h>
77 #import <WebCore/Page.h>
78 #import <WebCore/PluginData.h>
79 #import <WebCore/PrintContext.h>
80 #import <WebCore/RenderLayer.h>
81 #import <WebCore/RenderPart.h>
82 #import <WebCore/RenderView.h>
83 #import <WebCore/ReplaceSelectionCommand.h>
84 #import <WebCore/RuntimeApplicationChecks.h>
85 #import <WebCore/ScriptValue.h>
86 #import <WebCore/SmartReplace.h>
87 #import <WebCore/SVGDocumentExtensions.h>
88 #import <WebCore/SVGSMILElement.h>
89 #import <WebCore/TextIterator.h>
90 #import <WebCore/ThreadCheck.h>
91 #import <WebCore/TypingCommand.h>
92 #import <WebCore/htmlediting.h>
93 #import <WebCore/markup.h>
94 #import <WebCore/visible_units.h>
95 #import <WebKitSystemInterface.h>
96 #import <runtime/JSLock.h>
97 #import <runtime/JSObject.h>
98 #import <runtime/JSValue.h>
99 #import <wtf/CurrentTime.h>
100
101 using namespace std;
102 using namespace WebCore;
103 using namespace HTMLNames;
104
105 using JSC::JSGlobalObject;
106 using JSC::JSLock;
107 using JSC::JSValue;
108 using JSC::SilenceAssertionsOnly;
109
110 /*
111 Here is the current behavior matrix for four types of navigations:
112
113 Standard Nav:
114
115  Restore form state:   YES
116  Restore scroll and focus state:  YES
117  Cache policy: NSURLRequestUseProtocolCachePolicy
118  Add to back/forward list: YES
119  
120 Back/Forward:
121
122  Restore form state:   YES
123  Restore scroll and focus state:  YES
124  Cache policy: NSURLRequestReturnCacheDataElseLoad
125  Add to back/forward list: NO
126
127 Reload (meaning only the reload button):
128
129  Restore form state:   NO
130  Restore scroll and focus state:  YES
131  Cache policy: NSURLRequestReloadIgnoringCacheData
132  Add to back/forward list: NO
133
134 Repeat load of the same URL (by any other means of navigation other than the reload button, including hitting return in the location field):
135
136  Restore form state:   NO
137  Restore scroll and focus state:  NO, reset to initial conditions
138  Cache policy: NSURLRequestReloadIgnoringCacheData
139  Add to back/forward list: NO
140 */
141
142 NSString *WebPageCacheEntryDateKey = @"WebPageCacheEntryDateKey";
143 NSString *WebPageCacheDataSourceKey = @"WebPageCacheDataSourceKey";
144 NSString *WebPageCacheDocumentViewKey = @"WebPageCacheDocumentViewKey";
145
146 NSString *WebFrameMainDocumentError = @"WebFrameMainDocumentErrorKey";
147 NSString *WebFrameHasPlugins = @"WebFrameHasPluginsKey";
148 NSString *WebFrameHasUnloadListener = @"WebFrameHasUnloadListenerKey";
149 NSString *WebFrameUsesDatabases = @"WebFrameUsesDatabasesKey";
150 NSString *WebFrameUsesGeolocation = @"WebFrameUsesGeolocationKey";
151 NSString *WebFrameUsesApplicationCache = @"WebFrameUsesApplicationCacheKey";
152 NSString *WebFrameCanSuspendActiveDOMObjects = @"WebFrameCanSuspendActiveDOMObjectsKey";
153
154 // FIXME: Remove when this key becomes publicly defined
155 NSString *NSAccessibilityEnhancedUserInterfaceAttribute = @"AXEnhancedUserInterface";
156
157 @implementation WebFramePrivate
158
159 - (void)dealloc
160 {
161     [webFrameView release];
162
163     delete scriptDebugger;
164
165     [super dealloc];
166 }
167
168 - (void)finalize
169 {
170     delete scriptDebugger;
171
172     [super finalize];
173 }
174
175 - (void)setWebFrameView:(WebFrameView *)v 
176
177     [v retain];
178     [webFrameView release];
179     webFrameView = v;
180 }
181
182 @end
183
184 EditableLinkBehavior core(WebKitEditableLinkBehavior editableLinkBehavior)
185 {
186     switch (editableLinkBehavior) {
187         case WebKitEditableLinkDefaultBehavior:
188             return EditableLinkDefaultBehavior;
189         case WebKitEditableLinkAlwaysLive:
190             return EditableLinkAlwaysLive;
191         case WebKitEditableLinkOnlyLiveWithShiftKey:
192             return EditableLinkOnlyLiveWithShiftKey;
193         case WebKitEditableLinkLiveWhenNotFocused:
194             return EditableLinkLiveWhenNotFocused;
195         case WebKitEditableLinkNeverLive:
196             return EditableLinkNeverLive;
197     }
198     ASSERT_NOT_REACHED();
199     return EditableLinkDefaultBehavior;
200 }
201
202 WebCore::EditingBehaviorType core(WebKitEditingBehavior behavior)
203 {
204     switch (behavior) {
205         case WebKitEditingMacBehavior:
206             return WebCore::EditingMacBehavior;
207         case WebKitEditingWinBehavior:
208             return WebCore::EditingWindowsBehavior;
209         case WebKitEditingUnixBehavior:
210             return WebCore::EditingUnixBehavior;
211     }
212     ASSERT_NOT_REACHED();
213     return WebCore::EditingMacBehavior;
214 }
215
216 TextDirectionSubmenuInclusionBehavior core(WebTextDirectionSubmenuInclusionBehavior behavior)
217 {
218     switch (behavior) {
219         case WebTextDirectionSubmenuNeverIncluded:
220             return TextDirectionSubmenuNeverIncluded;
221         case WebTextDirectionSubmenuAutomaticallyIncluded:
222             return TextDirectionSubmenuAutomaticallyIncluded;
223         case WebTextDirectionSubmenuAlwaysIncluded:
224             return TextDirectionSubmenuAlwaysIncluded;
225     }
226     ASSERT_NOT_REACHED();
227     return TextDirectionSubmenuNeverIncluded;
228 }
229
230 @implementation WebFrame (WebInternal)
231
232 Frame* core(WebFrame *frame)
233 {
234     return frame ? frame->_private->coreFrame : 0;
235 }
236
237 WebFrame *kit(Frame* frame)
238 {
239     return frame ? static_cast<WebFrameLoaderClient*>(frame->loader()->client())->webFrame() : nil;
240 }
241
242 Page* core(WebView *webView)
243 {
244     return [webView page];
245 }
246
247 WebView *kit(Page* page)
248 {
249     return page ? static_cast<WebChromeClient*>(page->chrome()->client())->webView() : nil;
250 }
251
252 WebView *getWebView(WebFrame *webFrame)
253 {
254     Frame* coreFrame = core(webFrame);
255     if (!coreFrame)
256         return nil;
257     return kit(coreFrame->page());
258 }
259
260 + (PassRefPtr<Frame>)_createFrameWithPage:(Page*)page frameName:(const String&)name frameView:(WebFrameView *)frameView ownerElement:(HTMLFrameOwnerElement*)ownerElement
261 {
262     WebView *webView = kit(page);
263
264     WebFrame *frame = [[self alloc] _initWithWebFrameView:frameView webView:webView];
265     RefPtr<Frame> coreFrame = Frame::create(page, ownerElement, new WebFrameLoaderClient(frame));
266     [frame release];
267     frame->_private->coreFrame = coreFrame.get();
268
269     coreFrame->tree()->setName(name);
270     if (ownerElement) {
271         ASSERT(ownerElement->document()->frame());
272         ownerElement->document()->frame()->tree()->appendChild(coreFrame.get());
273     }
274
275     coreFrame->init();
276
277     [webView _setZoomMultiplier:[webView _realZoomMultiplier] isTextOnly:[webView _realZoomMultiplierIsTextOnly]];
278
279     return coreFrame.release();
280 }
281
282 + (void)_createMainFrameWithPage:(Page*)page frameName:(const String&)name frameView:(WebFrameView *)frameView
283 {
284     [self _createFrameWithPage:page frameName:name frameView:frameView ownerElement:0];
285 }
286
287 + (PassRefPtr<WebCore::Frame>)_createSubframeWithOwnerElement:(HTMLFrameOwnerElement*)ownerElement frameName:(const String&)name frameView:(WebFrameView *)frameView
288 {
289     return [self _createFrameWithPage:ownerElement->document()->frame()->page() frameName:name frameView:frameView ownerElement:ownerElement];
290 }
291
292 - (BOOL)_isIncludedInWebKitStatistics
293 {
294     return _private && _private->includedInWebKitStatistics;
295 }
296
297 - (void)_attachScriptDebugger
298 {
299     ScriptController* scriptController = _private->coreFrame->script();
300
301     // Calling ScriptController::globalObject() would create a window shell, and dispatch corresponding callbacks, which may be premature
302     // if the script debugger is attached before a document is created.  These calls use the debuggerWorld(), we will need to pass a world
303     // to be able to debug isolated worlds.
304     if (!scriptController->existingWindowShell(debuggerWorld()))
305         return;
306
307     JSGlobalObject* globalObject = scriptController->globalObject(debuggerWorld());
308     if (!globalObject)
309         return;
310
311     if (_private->scriptDebugger) {
312         ASSERT(_private->scriptDebugger == globalObject->debugger());
313         return;
314     }
315
316     _private->scriptDebugger = new WebScriptDebugger(globalObject);
317 }
318
319 - (void)_detachScriptDebugger
320 {
321     if (!_private->scriptDebugger)
322         return;
323
324     delete _private->scriptDebugger;
325     _private->scriptDebugger = 0;
326 }
327
328 - (id)_initWithWebFrameView:(WebFrameView *)fv webView:(WebView *)v
329 {
330     self = [super init];
331     if (!self)
332         return nil;
333
334     _private = [[WebFramePrivate alloc] init];
335
336     // Set includedInWebKitStatistics before calling WebFrameView _setWebFrame, since
337     // it calls WebFrame _isIncludedInWebKitStatistics.
338     if ((_private->includedInWebKitStatistics = [[v class] shouldIncludeInWebKitStatistics]))
339         ++WebFrameCount;
340
341     if (fv) {
342         [_private setWebFrameView:fv];
343         [fv _setWebFrame:self];
344     }
345
346     _private->shouldCreateRenderers = YES;
347
348     return self;
349 }
350
351 - (void)_clearCoreFrame
352 {
353     _private->coreFrame = 0;
354 }
355
356 - (void)_updateBackgroundAndUpdatesWhileOffscreen
357 {
358     WebView *webView = getWebView(self);
359     BOOL drawsBackground = [webView drawsBackground];
360     NSColor *backgroundColor = [webView backgroundColor];
361
362     Frame* coreFrame = _private->coreFrame;
363     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
364         if ([webView _usesDocumentViews]) {
365             // Don't call setDrawsBackground:YES here because it may be NO because of a load
366             // in progress; WebFrameLoaderClient keeps it set to NO during the load process.
367             WebFrame *webFrame = kit(frame);
368             if (!drawsBackground)
369                 [[[webFrame frameView] _scrollView] setDrawsBackground:NO];
370             [[[webFrame frameView] _scrollView] setBackgroundColor:backgroundColor];
371             id documentView = [[webFrame frameView] documentView];
372             if ([documentView respondsToSelector:@selector(setDrawsBackground:)])
373                 [documentView setDrawsBackground:drawsBackground];
374             if ([documentView respondsToSelector:@selector(setBackgroundColor:)])
375                 [documentView setBackgroundColor:backgroundColor];
376         }
377
378         if (FrameView* view = frame->view()) {
379             view->setTransparent(!drawsBackground);
380             view->setBaseBackgroundColor(colorFromNSColor([backgroundColor colorUsingColorSpaceName:NSDeviceRGBColorSpace]));
381             view->setShouldUpdateWhileOffscreen([webView shouldUpdateWhileOffscreen]);
382         }
383     }
384 }
385
386 - (void)_setInternalLoadDelegate:(id)internalLoadDelegate
387 {
388     _private->internalLoadDelegate = internalLoadDelegate;
389 }
390
391 - (id)_internalLoadDelegate
392 {
393     return _private->internalLoadDelegate;
394 }
395
396 - (void)_unmarkAllBadGrammar
397 {
398     Frame* coreFrame = _private->coreFrame;
399     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
400         if (Document* document = frame->document())
401             document->markers()->removeMarkers(DocumentMarker::Grammar);
402     }
403 }
404
405 - (void)_unmarkAllMisspellings
406 {
407     Frame* coreFrame = _private->coreFrame;
408     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
409         if (Document* document = frame->document())
410             document->markers()->removeMarkers(DocumentMarker::Spelling);
411     }
412 }
413
414 - (BOOL)_hasSelection
415 {
416     if ([getWebView(self) _usesDocumentViews]) {
417         id documentView = [_private->webFrameView documentView];    
418
419         // optimization for common case to avoid creating potentially large selection string
420         if ([documentView isKindOfClass:[WebHTMLView class]])
421             if (Frame* coreFrame = _private->coreFrame)
422                 return coreFrame->selection()->isRange();
423
424         if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
425             return [[documentView selectedString] length] > 0;
426         
427         return NO;
428     }
429
430     Frame* coreFrame = _private->coreFrame;
431     return coreFrame && coreFrame->selection()->isRange();
432 }
433
434 - (void)_clearSelection
435 {
436     ASSERT([getWebView(self) _usesDocumentViews]);
437     id documentView = [_private->webFrameView documentView];    
438     if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
439         [documentView deselectAll];
440 }
441
442 #if !ASSERT_DISABLED
443 - (BOOL)_atMostOneFrameHasSelection
444 {
445     // FIXME: 4186050 is one known case that makes this debug check fail.
446     BOOL found = NO;
447     Frame* coreFrame = _private->coreFrame;
448     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
449         if ([kit(frame) _hasSelection]) {
450             if (found)
451                 return NO;
452             found = YES;
453         }
454     return YES;
455 }
456 #endif
457
458 - (WebFrame *)_findFrameWithSelection
459 {
460     Frame* coreFrame = _private->coreFrame;
461     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
462         WebFrame *webFrame = kit(frame);
463         if ([webFrame _hasSelection])
464             return webFrame;
465     }
466     return nil;
467 }
468
469 - (void)_clearSelectionInOtherFrames
470 {
471     // We rely on WebDocumentSelection protocol implementors to call this method when they become first 
472     // responder. It would be nicer to just notice first responder changes here instead, but there's no 
473     // notification sent when the first responder changes in general (Radar 2573089).
474     WebFrame *frameWithSelection = [[getWebView(self) mainFrame] _findFrameWithSelection];
475     if (frameWithSelection != self)
476         [frameWithSelection _clearSelection];
477
478     // While we're in the general area of selection and frames, check that there is only one now.
479     ASSERT([[getWebView(self) mainFrame] _atMostOneFrameHasSelection]);
480 }
481
482 static inline WebDataSource *dataSource(DocumentLoader* loader)
483 {
484     return loader ? static_cast<WebDocumentLoaderMac*>(loader)->dataSource() : nil;
485 }
486
487 - (WebDataSource *)_dataSource
488 {
489     return dataSource(_private->coreFrame->loader()->documentLoader());
490 }
491
492 - (NSString *)_stringWithDocumentTypeStringAndMarkupString:(NSString *)markupString
493 {
494     return _private->coreFrame->documentTypeString() + markupString;
495 }
496
497 - (NSArray *)_nodesFromList:(Vector<Node*> *)nodesVector
498 {
499     size_t size = nodesVector->size();
500     NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:size];
501     for (size_t i = 0; i < size; ++i)
502         [nodes addObject:kit((*nodesVector)[i])];
503     return nodes;
504 }
505
506 - (NSString *)_markupStringFromRange:(DOMRange *)range nodes:(NSArray **)nodes
507 {
508     // FIXME: This is always "for interchange". Is that right? See the previous method.
509     Vector<Node*> nodeList;
510     NSString *markupString = createMarkup(core(range), nodes ? &nodeList : 0, AnnotateForInterchange);
511     if (nodes)
512         *nodes = [self _nodesFromList:&nodeList];
513
514     return [self _stringWithDocumentTypeStringAndMarkupString:markupString];
515 }
516
517 - (NSString *)_selectedString
518 {
519     return _private->coreFrame->displayStringModifiedByEncoding(_private->coreFrame->editor()->selectedText());
520 }
521
522 - (NSString *)_stringForRange:(DOMRange *)range
523 {
524     // This will give a system malloc'd buffer that can be turned directly into an NSString
525     unsigned length;
526     UChar* buf = plainTextToMallocAllocatedBuffer(core(range), length, true);
527     
528     if (!buf)
529         return [NSString string];
530
531     // Transfer buffer ownership to NSString
532     return [[[NSString alloc] initWithCharactersNoCopy:buf length:length freeWhenDone:YES] autorelease];
533 }
534
535 - (BOOL)_shouldFlattenCompositingLayers:(CGContextRef)context
536 {
537     // -currentContextDrawingToScreen returns YES for bitmap contexts.
538     BOOL isPrinting = ![NSGraphicsContext currentContextDrawingToScreen];
539     if (isPrinting)
540         return YES;
541
542     if (!WKCGContextIsBitmapContext(context))
543         return NO;
544
545     // If we're drawing into a bitmap, we might be snapshotting, or drawing into a layer-backed view.
546     if ([getWebView(self) _usesDocumentViews]) {
547         id documentView = [_private->webFrameView documentView];
548         if ([documentView isKindOfClass:[WebHTMLView class]] && [(WebHTMLView *)documentView _web_isDrawingIntoLayer])
549             return NO;
550     }
551
552     return [getWebView(self) _includesFlattenedCompositingLayersWhenDrawingToBitmap];
553 }
554
555 - (void)_drawRect:(NSRect)rect contentsOnly:(BOOL)contentsOnly
556 {
557     ASSERT([[NSGraphicsContext currentContext] isFlipped]);
558
559     CGContextRef ctx = static_cast<CGContextRef>([[NSGraphicsContext currentContext] graphicsPort]);
560     GraphicsContext context(ctx);
561
562     FrameView* view = _private->coreFrame->view();
563     
564     bool shouldFlatten = false;
565     if (Frame* parentFrame = _private->coreFrame->tree()->parent()) {
566         // For subframes, we need to inherit the paint behavior from our parent
567         FrameView* parentView = parentFrame ? parentFrame->view() : 0;
568         if (parentView)
569             shouldFlatten = parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers;
570     } else
571         shouldFlatten = [self _shouldFlattenCompositingLayers:ctx];
572
573     PaintBehavior oldBehavior = PaintBehaviorNormal;
574     if (shouldFlatten) {
575         oldBehavior = view->paintBehavior();
576         view->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
577     }
578     
579     if (contentsOnly)
580         view->paintContents(&context, enclosingIntRect(rect));
581     else
582         view->paint(&context, enclosingIntRect(rect));
583
584     if (shouldFlatten)
585         view->setPaintBehavior(oldBehavior);
586 }
587
588 - (BOOL)_getVisibleRect:(NSRect*)rect
589 {
590     ASSERT_ARG(rect, rect);
591     if (RenderPart* ownerRenderer = _private->coreFrame->ownerRenderer()) {
592         if (ownerRenderer->needsLayout())
593             return NO;
594         *rect = ownerRenderer->absoluteClippedOverflowRect();
595         return YES;
596     }
597
598     return NO;
599 }
600
601 - (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string
602 {
603     return [self _stringByEvaluatingJavaScriptFromString:string forceUserGesture:true];
604 }
605
606 - (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string forceUserGesture:(BOOL)forceUserGesture
607 {
608     ASSERT(_private->coreFrame->document());
609     
610     JSValue result = _private->coreFrame->script()->executeScript(string, forceUserGesture).jsValue();
611
612     if (!_private->coreFrame) // In case the script removed our frame from the page.
613         return @"";
614
615     // This bizarre set of rules matches behavior from WebKit for Safari 2.0.
616     // If you don't like it, use -[WebScriptObject evaluateWebScript:] or 
617     // JSEvaluateScript instead, since they have less surprising semantics.
618     if (!result || (!result.isBoolean() && !result.isString() && !result.isNumber()))
619         return @"";
620
621     JSLock lock(SilenceAssertionsOnly);
622     return ustringToString(result.toString(_private->coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec()));
623 }
624
625 - (NSRect)_caretRectAtPosition:(const Position&)pos affinity:(NSSelectionAffinity)affinity
626 {
627     VisiblePosition visiblePosition(pos, static_cast<EAffinity>(affinity));
628     return visiblePosition.absoluteCaretBounds();
629 }
630
631 - (NSRect)_firstRectForDOMRange:(DOMRange *)range
632 {
633    return _private->coreFrame->editor()->firstRectForRange(core(range));
634 }
635
636 - (void)_scrollDOMRangeToVisible:(DOMRange *)range
637 {
638     NSRect rangeRect = [self _firstRectForDOMRange:range];    
639     Node *startNode = core([range startContainer]);
640         
641     if (startNode && startNode->renderer()) {
642         RenderLayer *layer = startNode->renderer()->enclosingLayer();
643         if (layer)
644             layer->scrollRectToVisible(enclosingIntRect(rangeRect), false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
645     }
646 }
647
648 - (BOOL)_needsLayout
649 {
650     return _private->coreFrame->view() ? _private->coreFrame->view()->needsLayout() : false;
651 }
652
653 - (DOMRange *)_rangeByAlteringCurrentSelection:(SelectionController::EAlteration)alteration direction:(SelectionDirection)direction granularity:(TextGranularity)granularity
654 {
655     if (_private->coreFrame->selection()->isNone())
656         return nil;
657
658     SelectionController selection;
659     selection.setSelection(_private->coreFrame->selection()->selection());
660     selection.modify(alteration, direction, granularity);
661     return kit(selection.toNormalizedRange().get());
662 }
663
664 - (TextGranularity)_selectionGranularity
665 {
666     return _private->coreFrame->selection()->granularity();
667 }
668
669 - (NSRange)_convertToNSRange:(Range *)range
670 {
671     if (!range)
672         return NSMakeRange(NSNotFound, 0);
673
674     size_t location;
675     size_t length;
676     if (!TextIterator::locationAndLengthFromRange(range, location, length))
677         return NSMakeRange(NSNotFound, 0);
678
679     return NSMakeRange(location, length);
680 }
681
682 - (PassRefPtr<Range>)_convertToDOMRange:(NSRange)nsrange
683 {
684     if (nsrange.location > INT_MAX)
685         return 0;
686     if (nsrange.length > INT_MAX || nsrange.location + nsrange.length > INT_MAX)
687         nsrange.length = INT_MAX - nsrange.location;
688
689     // our critical assumption is that we are only called by input methods that
690     // concentrate on a given area containing the selection
691     // We have to do this because of text fields and textareas. The DOM for those is not
692     // directly in the document DOM, so serialization is problematic. Our solution is
693     // to use the root editable element of the selection start as the positional base.
694     // That fits with AppKit's idea of an input context.
695     Element* selectionRoot = _private->coreFrame->selection()->rootEditableElement();
696     Element* scope = selectionRoot ? selectionRoot : _private->coreFrame->document()->documentElement();
697     return TextIterator::rangeFromLocationAndLength(scope, nsrange.location, nsrange.length);
698 }
699
700 - (DOMRange *)convertNSRangeToDOMRange:(NSRange)nsrange
701 {
702     // This method exists to maintain compatibility with Leopard's Dictionary.app. <rdar://problem/6002160>
703     return [self _convertNSRangeToDOMRange:nsrange];
704 }
705
706 - (DOMRange *)_convertNSRangeToDOMRange:(NSRange)nsrange
707 {
708     return kit([self _convertToDOMRange:nsrange].get());
709 }
710
711 - (NSRange)convertDOMRangeToNSRange:(DOMRange *)range
712 {
713     // This method exists to maintain compatibility with Leopard's Dictionary.app. <rdar://problem/6002160>
714     return [self _convertDOMRangeToNSRange:range];
715 }
716
717 - (NSRange)_convertDOMRangeToNSRange:(DOMRange *)range
718 {
719     return [self _convertToNSRange:core(range)];
720 }
721
722 - (DOMRange *)_markDOMRange
723 {
724     return kit(_private->coreFrame->editor()->mark().toNormalizedRange().get());
725 }
726
727 // Given proposedRange, returns an extended range that includes adjacent whitespace that should
728 // be deleted along with the proposed range in order to preserve proper spacing and punctuation of
729 // the text surrounding the deletion.
730 - (DOMRange *)_smartDeleteRangeForProposedRange:(DOMRange *)proposedRange
731 {
732     Node* startContainer = core([proposedRange startContainer]);
733     Node* endContainer = core([proposedRange endContainer]);
734     if (startContainer == nil || endContainer == nil)
735         return nil;
736
737     ASSERT(startContainer->document() == endContainer->document());
738     
739     _private->coreFrame->document()->updateLayoutIgnorePendingStylesheets();
740
741     Position start(startContainer, [proposedRange startOffset]);
742     Position end(endContainer, [proposedRange endOffset]);
743     Position newStart = start.upstream().leadingWhitespacePosition(DOWNSTREAM, true);
744     if (newStart.isNull())
745         newStart = start;
746     Position newEnd = end.downstream().trailingWhitespacePosition(DOWNSTREAM, true);
747     if (newEnd.isNull())
748         newEnd = end;
749
750     newStart = newStart.parentAnchoredEquivalent();
751     newEnd = newEnd.parentAnchoredEquivalent();
752
753     RefPtr<Range> range = _private->coreFrame->document()->createRange();
754     int exception = 0;
755     range->setStart(newStart.containerNode(), newStart.offsetInContainerNode(), exception);
756     range->setEnd(newStart.containerNode(), newStart.offsetInContainerNode(), exception);
757     return kit(range.get());
758 }
759
760 - (DOMDocumentFragment *)_documentFragmentWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString 
761 {
762     if (!_private->coreFrame || !_private->coreFrame->document())
763         return nil;
764
765     return kit(createFragmentFromMarkup(_private->coreFrame->document(), markupString, baseURLString, FragmentScriptingNotAllowed).get());
766 }
767
768 - (DOMDocumentFragment *)_documentFragmentWithNodesAsParagraphs:(NSArray *)nodes
769 {
770     if (!_private->coreFrame || !_private->coreFrame->document())
771         return nil;
772     
773     NSEnumerator *nodeEnum = [nodes objectEnumerator];
774     Vector<Node*> nodesVector;
775     DOMNode *node;
776     while ((node = [nodeEnum nextObject]))
777         nodesVector.append(core(node));
778     
779     return kit(createFragmentFromNodes(_private->coreFrame->document(), nodesVector).get());
780 }
781
782 - (void)_replaceSelectionWithNode:(DOMNode *)node selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle
783 {
784     DOMDocumentFragment *fragment = kit(_private->coreFrame->document()->createDocumentFragment().get());
785     [fragment appendChild:node];
786     [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:matchStyle];
787 }
788
789 - (void)_insertParagraphSeparatorInQuotedContent
790 {
791     if (_private->coreFrame->selection()->isNone())
792         return;
793     
794     TypingCommand::insertParagraphSeparatorInQuotedContent(_private->coreFrame->document());
795     _private->coreFrame->selection()->revealSelection(ScrollAlignment::alignToEdgeIfNeeded);
796 }
797
798 - (VisiblePosition)_visiblePositionForPoint:(NSPoint)point
799 {
800     // FIXME: Someone with access to Apple's sources could remove this needless wrapper call.
801     return _private->coreFrame->visiblePositionForPoint(IntPoint(point));
802 }
803
804 - (DOMRange *)_characterRangeAtPoint:(NSPoint)point
805 {
806     return kit(_private->coreFrame->rangeForPoint(IntPoint(point)).get());
807 }
808
809 - (DOMCSSStyleDeclaration *)_typingStyle
810 {
811     if (!_private->coreFrame)
812         return nil;
813     RefPtr<CSSMutableStyleDeclaration> typingStyle = _private->coreFrame->selection()->copyTypingStyle();
814     if (!typingStyle)
815         return nil;
816     return kit(typingStyle.get());
817 }
818
819 - (void)_setTypingStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(EditAction)undoAction
820 {
821     if (!_private->coreFrame)
822         return;
823     _private->coreFrame->editor()->computeAndSetTypingStyle(core(style), undoAction);
824 }
825
826 - (void)_dragSourceEndedAt:(NSPoint)windowLoc operation:(NSDragOperation)operation
827 {
828     if (!_private->coreFrame)
829         return;
830     FrameView* view = _private->coreFrame->view();
831     if (!view)
832         return;
833     ASSERT([getWebView(self) _usesDocumentViews]);
834     // FIXME: These are fake modifier keys here, but they should be real ones instead.
835     PlatformMouseEvent event(IntPoint(windowLoc), globalPoint(windowLoc, [view->platformWidget() window]),
836         LeftButton, MouseEventMoved, 0, false, false, false, false, currentTime());
837     _private->coreFrame->eventHandler()->dragSourceEndedAt(event, (DragOperation)operation);
838 }
839
840 - (BOOL)_canProvideDocumentSource
841 {
842     Frame* frame = _private->coreFrame;
843     String mimeType = frame->document()->loader()->writer()->mimeType();
844     PluginData* pluginData = frame->page() ? frame->page()->pluginData() : 0;
845
846     if (WebCore::DOMImplementation::isTextMIMEType(mimeType) ||
847         Image::supportsType(mimeType) ||
848         (pluginData && pluginData->supportsMimeType(mimeType)))
849         return NO;
850
851     return YES;
852 }
853
854 - (BOOL)_canSaveAsWebArchive
855 {
856     // Currently, all documents that we can view source for
857     // (HTML and XML documents) can also be saved as web archives
858     return [self _canProvideDocumentSource];
859 }
860
861 - (void)_commitData:(NSData *)data
862 {
863     // FIXME: This really should be a setting.
864     Document* document = _private->coreFrame->document();
865     document->setShouldCreateRenderers(_private->shouldCreateRenderers);
866
867     _private->coreFrame->loader()->documentLoader()->commitData((const char *)[data bytes], [data length]);
868 }
869
870 @end
871
872 @implementation WebFrame (WebPrivate)
873
874 // FIXME: This exists only as a convenience for Safari, consider moving there.
875 - (BOOL)_isDescendantOfFrame:(WebFrame *)ancestor
876 {
877     Frame* coreFrame = _private->coreFrame;
878     return coreFrame && coreFrame->tree()->isDescendantOf(core(ancestor));
879 }
880
881 - (void)_setShouldCreateRenderers:(BOOL)shouldCreateRenderers
882 {
883     _private->shouldCreateRenderers = shouldCreateRenderers;
884 }
885
886 - (NSColor *)_bodyBackgroundColor
887 {
888     Document* document = _private->coreFrame->document();
889     if (!document)
890         return nil;
891     HTMLElement* body = document->body();
892     if (!body)
893         return nil;
894     RenderObject* bodyRenderer = body->renderer();
895     if (!bodyRenderer)
896         return nil;
897     Color color = bodyRenderer->style()->visitedDependentColor(CSSPropertyBackgroundColor);
898     if (!color.isValid())
899         return nil;
900     return nsColor(color);
901 }
902
903 - (BOOL)_isFrameSet
904 {
905     Document* document = _private->coreFrame->document();
906     return document && document->isFrameSet();
907 }
908
909 - (BOOL)_firstLayoutDone
910 {
911     return _private->coreFrame->loader()->stateMachine()->firstLayoutDone();
912 }
913
914 - (WebFrameLoadType)_loadType
915 {
916     return (WebFrameLoadType)_private->coreFrame->loader()->loadType();
917 }
918
919 - (NSRange)_selectedNSRange
920 {
921     return [self _convertToNSRange:_private->coreFrame->selection()->toNormalizedRange().get()];
922 }
923
924 - (void)_selectNSRange:(NSRange)range
925 {
926     RefPtr<Range> domRange = [self _convertToDOMRange:range];
927     if (domRange)
928         _private->coreFrame->selection()->setSelection(VisibleSelection(domRange.get(), SEL_DEFAULT_AFFINITY));
929 }
930
931 - (BOOL)_isDisplayingStandaloneImage
932 {
933     Document* document = _private->coreFrame->document();
934     return document && document->isImageDocument();
935 }
936
937 - (unsigned)_pendingFrameUnloadEventCount
938 {
939     return _private->coreFrame->domWindow()->pendingUnloadEventListeners();
940 }
941
942 - (void)_setIsDisconnected:(bool)isDisconnected
943 {
944     _private->coreFrame->setIsDisconnected(isDisconnected);
945 }
946
947 - (void)_setExcludeFromTextSearch:(bool)exclude
948 {
949     _private->coreFrame->setExcludeFromTextSearch(exclude);
950 }
951
952 #if ENABLE(NETSCAPE_PLUGIN_API)
953 - (void)_recursive_resumeNullEventsForAllNetscapePlugins
954 {
955     Frame* coreFrame = core(self);
956     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
957         NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView];
958         if ([documentView isKindOfClass:[WebHTMLView class]])
959             [(WebHTMLView *)documentView _resumeNullEventsForAllNetscapePlugins];
960     }
961 }
962
963 - (void)_recursive_pauseNullEventsForAllNetscapePlugins
964 {
965     Frame* coreFrame = core(self);
966     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
967         NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView];
968         if ([documentView isKindOfClass:[WebHTMLView class]])
969             [(WebHTMLView *)documentView _pauseNullEventsForAllNetscapePlugins];
970     }
971 }
972 #endif
973
974 - (BOOL)_pauseAnimation:(NSString*)name onNode:(DOMNode *)node atTime:(NSTimeInterval)time
975 {
976     Frame* frame = core(self);
977     if (!frame)
978         return false;
979
980     AnimationController* controller = frame->animation();
981     if (!controller)
982         return false;
983
984     Node* coreNode = core(node);
985     if (!coreNode || !coreNode->renderer())
986         return false;
987
988     return controller->pauseAnimationAtTime(coreNode->renderer(), name, time);
989 }
990
991 - (BOOL)_pauseTransitionOfProperty:(NSString*)name onNode:(DOMNode*)node atTime:(NSTimeInterval)time
992 {
993     Frame* frame = core(self);
994     if (!frame)
995         return false;
996
997     AnimationController* controller = frame->animation();
998     if (!controller)
999         return false;
1000
1001     Node* coreNode = core(node);
1002     if (!coreNode || !coreNode->renderer())
1003         return false;
1004
1005     return controller->pauseTransitionAtTime(coreNode->renderer(), name, time);
1006 }
1007
1008 // Pause a given SVG animation on the target node at a specific time.
1009 // This method is only intended to be used for testing the SVG animation system.
1010 - (BOOL)_pauseSVGAnimation:(NSString*)elementId onSMILNode:(DOMNode *)node atTime:(NSTimeInterval)time
1011 {
1012     Frame* frame = core(self);
1013     if (!frame)
1014         return false;
1015  
1016     Document* document = frame->document();
1017     if (!document || !document->svgExtensions())
1018         return false;
1019
1020     Node* coreNode = core(node);
1021     if (!coreNode || !SVGSMILElement::isSMILElement(coreNode))
1022         return false;
1023
1024 #if ENABLE(SVG)
1025     return document->accessSVGExtensions()->sampleAnimationAtTime(elementId, static_cast<SVGSMILElement*>(coreNode), time);
1026 #else
1027     return false;
1028 #endif
1029 }
1030
1031 - (unsigned) _numberOfActiveAnimations
1032 {
1033     Frame* frame = core(self);
1034     if (!frame)
1035         return false;
1036
1037     AnimationController* controller = frame->animation();
1038     if (!controller)
1039         return false;
1040
1041     return controller->numberOfActiveAnimations();
1042 }
1043
1044 - (void) _suspendAnimations
1045 {
1046     Frame* frame = core(self);
1047     if (!frame)
1048         return;
1049         
1050     frame->animation()->suspendAnimations();
1051 }
1052
1053 - (void) _resumeAnimations
1054 {
1055     Frame* frame = core(self);
1056     if (!frame)
1057         return;
1058
1059     frame->animation()->resumeAnimations();
1060 }
1061
1062 - (void)_replaceSelectionWithFragment:(DOMDocumentFragment *)fragment selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle
1063 {
1064     if (_private->coreFrame->selection()->isNone() || !fragment)
1065         return;
1066     ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::PreventNesting;
1067     if (selectReplacement)
1068         options |= ReplaceSelectionCommand::SelectReplacement;
1069     if (smartReplace)
1070         options |= ReplaceSelectionCommand::SmartReplace;
1071     if (matchStyle)
1072         options |= ReplaceSelectionCommand::MatchStyle;
1073     applyCommand(ReplaceSelectionCommand::create(_private->coreFrame->document(), core(fragment), options));
1074     _private->coreFrame->selection()->revealSelection(ScrollAlignment::alignToEdgeIfNeeded);
1075 }
1076
1077 - (void)_replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1078 {   
1079     DOMDocumentFragment* fragment = kit(createFragmentFromText(_private->coreFrame->selection()->toNormalizedRange().get(), text).get());
1080     [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:YES];
1081 }
1082
1083 - (void)_replaceSelectionWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1084 {
1085     DOMDocumentFragment *fragment = [self _documentFragmentWithMarkupString:markupString baseURLString:baseURLString];
1086     [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:NO];
1087 }
1088
1089 // Determines whether whitespace needs to be added around aString to preserve proper spacing and
1090 // punctuation when it's inserted into the receiver's text over charRange. Returns by reference
1091 // in beforeString and afterString any whitespace that should be added, unless either or both are
1092 // nil. Both are returned as nil if aString is nil or if smart insertion and deletion are disabled.
1093 - (void)_smartInsertForString:(NSString *)pasteString replacingRange:(DOMRange *)rangeToReplace beforeString:(NSString **)beforeString afterString:(NSString **)afterString
1094 {
1095     // give back nil pointers in case of early returns
1096     if (beforeString)
1097         *beforeString = nil;
1098     if (afterString)
1099         *afterString = nil;
1100         
1101     // inspect destination
1102     Node *startContainer = core([rangeToReplace startContainer]);
1103     Node *endContainer = core([rangeToReplace endContainer]);
1104
1105     Position startPos(startContainer, [rangeToReplace startOffset]);
1106     Position endPos(endContainer, [rangeToReplace endOffset]);
1107
1108     VisiblePosition startVisiblePos = VisiblePosition(startPos, VP_DEFAULT_AFFINITY);
1109     VisiblePosition endVisiblePos = VisiblePosition(endPos, VP_DEFAULT_AFFINITY);
1110     
1111     // this check also ensures startContainer, startPos, endContainer, and endPos are non-null
1112     if (startVisiblePos.isNull() || endVisiblePos.isNull())
1113         return;
1114
1115     bool addLeadingSpace = startPos.leadingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isStartOfParagraph(startVisiblePos);
1116     if (addLeadingSpace)
1117         if (UChar previousChar = startVisiblePos.previous().characterAfter())
1118             addLeadingSpace = !isCharacterSmartReplaceExempt(previousChar, true);
1119     
1120     bool addTrailingSpace = endPos.trailingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isEndOfParagraph(endVisiblePos);
1121     if (addTrailingSpace)
1122         if (UChar thisChar = endVisiblePos.characterAfter())
1123             addTrailingSpace = !isCharacterSmartReplaceExempt(thisChar, false);
1124     
1125     // inspect source
1126     bool hasWhitespaceAtStart = false;
1127     bool hasWhitespaceAtEnd = false;
1128     unsigned pasteLength = [pasteString length];
1129     if (pasteLength > 0) {
1130         NSCharacterSet *whiteSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
1131         
1132         if ([whiteSet characterIsMember:[pasteString characterAtIndex:0]]) {
1133             hasWhitespaceAtStart = YES;
1134         }
1135         if ([whiteSet characterIsMember:[pasteString characterAtIndex:(pasteLength - 1)]]) {
1136             hasWhitespaceAtEnd = YES;
1137         }
1138     }
1139     
1140     // issue the verdict
1141     if (beforeString && addLeadingSpace && !hasWhitespaceAtStart)
1142         *beforeString = @" ";
1143     if (afterString && addTrailingSpace && !hasWhitespaceAtEnd)
1144         *afterString = @" ";
1145 }
1146
1147 - (NSMutableDictionary *)_cacheabilityDictionary
1148 {
1149     NSMutableDictionary *result = [NSMutableDictionary dictionary];
1150     
1151     FrameLoader* frameLoader = _private->coreFrame->loader();
1152     DocumentLoader* documentLoader = frameLoader->documentLoader();
1153     if (documentLoader && !documentLoader->mainDocumentError().isNull())
1154         [result setObject:(NSError *)documentLoader->mainDocumentError() forKey:WebFrameMainDocumentError];
1155         
1156     if (frameLoader->subframeLoader()->containsPlugins())
1157         [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameHasPlugins];
1158     
1159     if (DOMWindow* domWindow = _private->coreFrame->domWindow()) {
1160         if (domWindow->hasEventListeners(eventNames().unloadEvent))
1161             [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameHasUnloadListener];
1162             
1163 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
1164         if (domWindow->optionalApplicationCache())
1165             [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameUsesApplicationCache];
1166 #endif
1167     }
1168     
1169     if (Document* document = _private->coreFrame->document()) {
1170 #if ENABLE(DATABASE)
1171         if (document->hasOpenDatabases())
1172             [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameUsesDatabases];
1173 #endif
1174             
1175         if (document->usingGeolocation())
1176             [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameUsesGeolocation];
1177             
1178         if (!document->canSuspendActiveDOMObjects())
1179             [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameCanSuspendActiveDOMObjects];
1180     }
1181     
1182     return result;
1183 }
1184
1185 - (BOOL)_allowsFollowingLink:(NSURL *)URL
1186 {
1187     if (!_private->coreFrame)
1188         return YES;
1189     return _private->coreFrame->document()->securityOrigin()->canDisplay(URL);
1190 }
1191
1192 - (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string withGlobalObject:(JSObjectRef)globalObjectRef inScriptWorld:(WebScriptWorld *)world
1193 {
1194     // Start off with some guess at a frame and a global object, we'll try to do better...!
1195     JSDOMWindow* anyWorldGlobalObject = _private->coreFrame->script()->globalObject(mainThreadNormalWorld());
1196
1197     // The global object is probably a shell object? - if so, we know how to use this!
1198     JSC::JSObject* globalObjectObj = toJS(globalObjectRef);
1199     if (!strcmp(globalObjectObj->classInfo()->className, "JSDOMWindowShell"))
1200         anyWorldGlobalObject = static_cast<JSDOMWindowShell*>(globalObjectObj)->window();
1201
1202     // Get the frame frome the global object we've settled on.
1203     Frame* frame = anyWorldGlobalObject->impl()->frame();
1204     ASSERT(frame->document());
1205     JSValue result = frame->script()->executeScriptInWorld(core(world), string, true).jsValue();
1206
1207     if (!frame) // In case the script removed our frame from the page.
1208         return @"";
1209
1210     // This bizarre set of rules matches behavior from WebKit for Safari 2.0.
1211     // If you don't like it, use -[WebScriptObject evaluateWebScript:] or 
1212     // JSEvaluateScript instead, since they have less surprising semantics.
1213     if (!result || (!result.isBoolean() && !result.isString() && !result.isNumber()))
1214         return @"";
1215
1216     JSLock lock(SilenceAssertionsOnly);
1217     return ustringToString(result.toString(anyWorldGlobalObject->globalExec()));
1218 }
1219
1220 - (JSGlobalContextRef)_globalContextForScriptWorld:(WebScriptWorld *)world
1221 {
1222     Frame* coreFrame = _private->coreFrame;
1223     if (!coreFrame)
1224         return 0;
1225     DOMWrapperWorld* coreWorld = core(world);
1226     if (!coreWorld)
1227         return 0;
1228     return toGlobalRef(coreFrame->script()->globalObject(coreWorld)->globalExec());
1229 }
1230
1231 - (void)setAllowsScrollersToOverlapContent:(BOOL)flag
1232 {
1233     ASSERT([[[self frameView] _scrollView] isKindOfClass:[WebDynamicScrollBarsView class]]);
1234     [(WebDynamicScrollBarsView *)[[self frameView] _scrollView] setAllowsScrollersToOverlapContent:flag];
1235 }
1236
1237 - (void)setAlwaysHideHorizontalScroller:(BOOL)flag
1238 {
1239     ASSERT([[[self frameView] _scrollView] isKindOfClass:[WebDynamicScrollBarsView class]]);
1240     [(WebDynamicScrollBarsView *)[[self frameView] _scrollView] setAlwaysHideHorizontalScroller:flag];
1241 }
1242 - (void)setAlwaysHideVerticalScroller:(BOOL)flag
1243 {
1244     ASSERT([[[self frameView] _scrollView] isKindOfClass:[WebDynamicScrollBarsView class]]);
1245     [(WebDynamicScrollBarsView *)[[self frameView] _scrollView] setAlwaysHideVerticalScroller:flag];
1246 }
1247
1248 - (void)setAccessibleName:(NSString *)name
1249 {
1250 #if HAVE(ACCESSIBILITY)
1251     if (!AXObjectCache::accessibilityEnabled())
1252         return;
1253     
1254     if (!_private->coreFrame || !_private->coreFrame->document())
1255         return;
1256     
1257     AccessibilityObject* rootObject = _private->coreFrame->document()->axObjectCache()->rootObject();
1258     if (rootObject) {
1259         String strName(name);
1260         rootObject->setAccessibleName(strName);
1261     }
1262 #endif
1263 }
1264
1265 - (NSString*)_layerTreeAsText
1266 {
1267     Frame* coreFrame = _private->coreFrame;
1268     if (!coreFrame)
1269         return @"";
1270
1271     return coreFrame->layerTreeAsText();
1272 }
1273
1274 - (BOOL)hasSpellingMarker:(int)from length:(int)length
1275 {
1276     Frame* coreFrame = core(self);
1277     if (!coreFrame)
1278         return NO;
1279     return coreFrame->editor()->selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
1280 }
1281
1282 - (BOOL)hasGrammarMarker:(int)from length:(int)length
1283 {
1284     Frame* coreFrame = core(self);
1285     if (!coreFrame)
1286         return NO;
1287     return coreFrame->editor()->selectionStartHasMarkerFor(DocumentMarker::Grammar, from, length);
1288 }
1289
1290 - (id)accessibilityRoot
1291 {
1292 #if HAVE(ACCESSIBILITY)
1293     if (!AXObjectCache::accessibilityEnabled()) {
1294         AXObjectCache::enableAccessibility();
1295         AXObjectCache::setEnhancedUserInterfaceAccessibility([[NSApp accessibilityAttributeValue:NSAccessibilityEnhancedUserInterfaceAttribute] boolValue]);
1296     }
1297     
1298     if (!_private->coreFrame || !_private->coreFrame->document())
1299         return nil;
1300     
1301     AccessibilityObject* rootObject = _private->coreFrame->document()->axObjectCache()->rootObjectForFrame(_private->coreFrame);
1302     if (!rootObject)
1303         return nil;
1304     
1305     // The root object will be a WebCore scroll view object. In WK1, scroll views are handled
1306     // by the system and the root object should be the web area (instead of the scroll view).
1307     if (rootObject->isAttachment() && rootObject->firstChild())
1308         return rootObject->firstChild()->wrapper();
1309     
1310     return rootObject->wrapper();
1311 #else
1312     return nil;
1313 #endif
1314 }
1315
1316 - (void)_clearOpener
1317 {
1318     Frame* coreFrame = _private->coreFrame;
1319     if (coreFrame)
1320         coreFrame->loader()->setOpener(0);
1321 }
1322
1323 // Used by pagination code called from AppKit when a standalone web page is printed.
1324 - (NSArray *)_computePageRectsWithPrintScaleFactor:(float)printScaleFactor pageSize:(NSSize)pageSize
1325 {
1326     if (printScaleFactor <= 0) {
1327         LOG_ERROR("printScaleFactor has bad value %.2f", printScaleFactor);
1328         return [NSArray array];
1329     }
1330
1331     if (!_private->coreFrame)
1332         return [NSArray array];
1333     if (!_private->coreFrame->document())
1334         return [NSArray array];
1335     if (!_private->coreFrame->view())
1336         return [NSArray array];
1337     if (!_private->coreFrame->view()->documentView())
1338         return [NSArray array];
1339
1340     RenderView* root = toRenderView(_private->coreFrame->document()->renderer());
1341     if (!root)
1342         return [NSArray array];
1343
1344     float printWidth = root->style()->isHorizontalWritingMode() ? root->docWidth() / printScaleFactor : pageSize.width;
1345     float printHeight = root->style()->isHorizontalWritingMode() ? pageSize.height : root->docHeight() / printScaleFactor;
1346
1347     PrintContext printContext(_private->coreFrame);
1348     printContext.computePageRectsWithPageSize(FloatSize(printWidth, printHeight), true);
1349     const Vector<IntRect>& pageRects = printContext.pageRects();
1350
1351     size_t size = pageRects.size();
1352     NSMutableArray *pages = [NSMutableArray arrayWithCapacity:size];
1353     for (size_t i = 0; i < size; ++i)
1354         [pages addObject:[NSValue valueWithRect:NSRect(pageRects[i])]];
1355     return pages;
1356 }
1357
1358 @end
1359
1360 @implementation WebFrame
1361
1362 - (id)init
1363 {
1364     return nil;
1365 }
1366
1367 // Should be deprecated.
1368 - (id)initWithName:(NSString *)name webFrameView:(WebFrameView *)view webView:(WebView *)webView
1369 {
1370     return nil;
1371 }
1372
1373 - (void)dealloc
1374 {
1375     if (_private && _private->includedInWebKitStatistics)
1376         --WebFrameCount;
1377
1378     [_private release];
1379
1380     [super dealloc];
1381 }
1382
1383 - (void)finalize
1384 {
1385     if (_private && _private->includedInWebKitStatistics)
1386         --WebFrameCount;
1387
1388     [super finalize];
1389 }
1390
1391 - (NSString *)name
1392 {
1393     Frame* coreFrame = _private->coreFrame;
1394     if (!coreFrame)
1395         return nil;
1396     return coreFrame->tree()->uniqueName();
1397 }
1398
1399 - (WebFrameView *)frameView
1400 {
1401     ASSERT(!getWebView(self) || [getWebView(self) _usesDocumentViews]);
1402     return _private->webFrameView;
1403 }
1404
1405 - (WebView *)webView
1406 {
1407     return getWebView(self);
1408 }
1409
1410 static bool needsMicrosoftMessengerDOMDocumentWorkaround()
1411 {
1412     static bool needsWorkaround = applicationIsMicrosoftMessenger() && [[[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey] compare:@"7.1" options:NSNumericSearch] == NSOrderedAscending;
1413     return needsWorkaround;
1414 }
1415
1416 - (DOMDocument *)DOMDocument
1417 {
1418     if (needsMicrosoftMessengerDOMDocumentWorkaround() && !pthread_main_np())
1419         return nil;
1420
1421     Frame* coreFrame = _private->coreFrame;
1422     if (!coreFrame)
1423         return nil;
1424     
1425     // FIXME: <rdar://problem/5145841> When loading a custom view/representation 
1426     // into a web frame, the old document can still be around. This makes sure that
1427     // we'll return nil in those cases.
1428     if (![[self _dataSource] _isDocumentHTML]) 
1429         return nil; 
1430
1431     Document* document = coreFrame->document();
1432     
1433     // According to the documentation, we should return nil if the frame doesn't have a document.
1434     // While full-frame images and plugins do have an underlying HTML document, we return nil here to be
1435     // backwards compatible.
1436     if (document && (document->isPluginDocument() || document->isImageDocument()))
1437         return nil;
1438     
1439     return kit(coreFrame->document());
1440 }
1441
1442 - (DOMHTMLElement *)frameElement
1443 {
1444     Frame* coreFrame = _private->coreFrame;
1445     if (!coreFrame)
1446         return nil;
1447     return kit(coreFrame->ownerElement());
1448 }
1449
1450 - (WebDataSource *)provisionalDataSource
1451 {
1452     Frame* coreFrame = _private->coreFrame;
1453     return coreFrame ? dataSource(coreFrame->loader()->provisionalDocumentLoader()) : nil;
1454 }
1455
1456 - (WebDataSource *)dataSource
1457 {
1458     Frame* coreFrame = _private->coreFrame;
1459     return coreFrame && coreFrame->loader()->frameHasLoaded() ? [self _dataSource] : nil;
1460 }
1461
1462 - (void)loadRequest:(NSURLRequest *)request
1463 {
1464     Frame* coreFrame = _private->coreFrame;
1465     if (!coreFrame)
1466         return;
1467     coreFrame->loader()->load(request, false);
1468 }
1469
1470 static NSURL *createUniqueWebDataURL()
1471 {
1472     CFUUIDRef UUIDRef = CFUUIDCreate(kCFAllocatorDefault);
1473     NSString *UUIDString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, UUIDRef);
1474     CFRelease(UUIDRef);
1475     NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"applewebdata://%@", UUIDString]];
1476     CFRelease(UUIDString);
1477     return URL;
1478 }
1479
1480 - (void)_loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL
1481 {
1482     if (!pthread_main_np())
1483         return [[self _webkit_invokeOnMainThread] _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:baseURL unreachableURL:unreachableURL];
1484     
1485     KURL responseURL;
1486     if (!baseURL) {
1487         baseURL = blankURL();
1488         responseURL = createUniqueWebDataURL();
1489     }
1490     
1491     ResourceRequest request([baseURL absoluteURL]);
1492
1493     // hack because Mail checks for this property to detect data / archive loads
1494     [NSURLProtocol setProperty:@"" forKey:@"WebDataRequest" inRequest:(NSMutableURLRequest *)request.nsURLRequest()];
1495
1496     SubstituteData substituteData(WebCore::SharedBuffer::wrapNSData(data), MIMEType, encodingName, [unreachableURL absoluteURL], responseURL);
1497
1498     _private->coreFrame->loader()->load(request, substituteData, false);
1499 }
1500
1501
1502 - (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL
1503 {
1504     WebCoreThreadViolationCheckRoundTwo();
1505     
1506     if (!MIMEType)
1507         MIMEType = @"text/html";
1508     [self _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:baseURL unreachableURL:nil];
1509 }
1510
1511 - (void)_loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL
1512 {
1513     NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
1514     [self _loadData:data MIMEType:@"text/html" textEncodingName:@"UTF-8" baseURL:baseURL unreachableURL:unreachableURL];
1515 }
1516
1517 - (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL
1518 {
1519     WebCoreThreadViolationCheckRoundTwo();
1520
1521     [self _loadHTMLString:string baseURL:baseURL unreachableURL:nil];
1522 }
1523
1524 - (void)loadAlternateHTMLString:(NSString *)string baseURL:(NSURL *)baseURL forUnreachableURL:(NSURL *)unreachableURL
1525 {
1526     WebCoreThreadViolationCheckRoundTwo();
1527
1528     [self _loadHTMLString:string baseURL:baseURL unreachableURL:unreachableURL];
1529 }
1530
1531 - (void)loadArchive:(WebArchive *)archive
1532 {
1533     if (LegacyWebArchive* coreArchive = [archive _coreLegacyWebArchive])
1534         _private->coreFrame->loader()->loadArchive(coreArchive);
1535 }
1536
1537 - (void)stopLoading
1538 {
1539     if (!_private->coreFrame)
1540         return;
1541     _private->coreFrame->loader()->stopForUserCancel();
1542 }
1543
1544 - (void)reload
1545 {
1546     if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_RELOAD_FROM_ORIGIN) && applicationIsSafari())
1547         _private->coreFrame->loader()->reload(GetCurrentKeyModifiers() & shiftKey);
1548     else
1549         _private->coreFrame->loader()->reload(false);
1550 }
1551
1552 - (void)reloadFromOrigin
1553 {
1554     _private->coreFrame->loader()->reload(true);
1555 }
1556
1557 - (WebFrame *)findFrameNamed:(NSString *)name
1558 {
1559     Frame* coreFrame = _private->coreFrame;
1560     if (!coreFrame)
1561         return nil;
1562     return kit(coreFrame->tree()->find(name));
1563 }
1564
1565 - (WebFrame *)parentFrame
1566 {
1567     Frame* coreFrame = _private->coreFrame;
1568     if (!coreFrame)
1569         return nil;
1570     return [[kit(coreFrame->tree()->parent()) retain] autorelease];
1571 }
1572
1573 - (NSArray *)childFrames
1574 {
1575     Frame* coreFrame = _private->coreFrame;
1576     if (!coreFrame)
1577         return [NSArray array];
1578     NSMutableArray *children = [NSMutableArray arrayWithCapacity:coreFrame->tree()->childCount()];
1579     for (Frame* child = coreFrame->tree()->firstChild(); child; child = child->tree()->nextSibling())
1580         [children addObject:kit(child)];
1581     return children;
1582 }
1583
1584 - (WebScriptObject *)windowObject
1585 {
1586     Frame* coreFrame = _private->coreFrame;
1587     if (!coreFrame)
1588         return 0;
1589     return coreFrame->script()->windowScriptObject();
1590 }
1591
1592 - (JSGlobalContextRef)globalContext
1593 {
1594     Frame* coreFrame = _private->coreFrame;
1595     if (!coreFrame)
1596         return 0;
1597     return toGlobalRef(coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec());
1598 }
1599
1600 @end