WebCore:
[WebKit-https.git] / 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 "WebChromeClient.h"
39 #import "WebDataSourceInternal.h"
40 #import "WebDocumentLoaderMac.h"
41 #import "WebFrameLoaderClient.h"
42 #import "WebFrameViewInternal.h"
43 #import "WebHTMLViewInternal.h"
44 #import "WebKitLogging.h"
45 #import "WebKitStatisticsPrivate.h"
46 #import "WebNSURLExtras.h"
47 #import "WebScriptDebugger.h"
48 #import "WebViewInternal.h"
49 #import <JavaScriptCore/APICast.h>
50 #import <JavaScriptCore/array_object.h>
51 #import <JavaScriptCore/date_object.h>
52 #import <WebCore/AXObjectCache.h>
53 #import <WebCore/ColorMac.h>
54 #import <WebCore/DOMImplementation.h>
55 #import <WebCore/DocLoader.h>
56 #import <WebCore/DocumentFragment.h>
57 #import <WebCore/Editor.h>
58 #import <WebCore/EventHandler.h>
59 #import <WebCore/Frame.h>
60 #import <WebCore/FrameLoader.h>
61 #import <WebCore/FrameTree.h>
62 #import <WebCore/GraphicsContext.h>
63 #import <WebCore/HTMLFrameOwnerElement.h>
64 #import <WebCore/HTMLInputElement.h>
65 #import <WebCore/HistoryItem.h>
66 #import <WebCore/HitTestResult.h>
67 #import <WebCore/Page.h>
68 #import <WebCore/PluginData.h>
69 #import <WebCore/RenderTreeAsText.h>
70 #import <WebCore/RenderView.h>
71 #import <WebCore/RenderWidget.h>
72 #import <WebCore/ReplaceSelectionCommand.h>
73 #import <WebCore/SimpleFontData.h>
74 #import <WebCore/SmartReplace.h>
75 #import <WebCore/SystemTime.h>
76 #import <WebCore/TextIterator.h>
77 #import <WebCore/TextResourceDecoder.h>
78 #import <WebCore/TypingCommand.h>
79 #import <WebCore/htmlediting.h>
80 #import <WebCore/kjs_proxy.h>
81 #import <WebCore/markup.h>
82 #import <WebCore/visible_units.h>
83
84 using namespace std;
85 using namespace WebCore;
86 using namespace HTMLNames;
87
88 using KJS::ArrayInstance;
89 using KJS::BooleanType;
90 using KJS::DateInstance;
91 using KJS::ExecState;
92 using KJS::GetterSetterType;
93 using KJS::JSGlobalObject;
94 using KJS::JSLock;
95 using KJS::JSObject;
96 using KJS::JSValue;
97 using KJS::NullType;
98 using KJS::NumberType;
99 using KJS::ObjectType;
100 using KJS::StringType;
101 using KJS::UndefinedType;
102 using KJS::UnspecifiedType;
103
104 /*
105 Here is the current behavior matrix for four types of navigations:
106
107 Standard Nav:
108
109  Restore form state:   YES
110  Restore scroll and focus state:  YES
111  Cache policy: NSURLRequestUseProtocolCachePolicy
112  Add to back/forward list: YES
113  
114 Back/Forward:
115
116  Restore form state:   YES
117  Restore scroll and focus state:  YES
118  Cache policy: NSURLRequestReturnCacheDataElseLoad
119  Add to back/forward list: NO
120
121 Reload (meaning only the reload button):
122
123  Restore form state:   NO
124  Restore scroll and focus state:  YES
125  Cache policy: NSURLRequestReloadIgnoringCacheData
126  Add to back/forward list: NO
127
128 Repeat load of the same URL (by any other means of navigation other than the reload button, including hitting return in the location field):
129
130  Restore form state:   NO
131  Restore scroll and focus state:  NO, reset to initial conditions
132  Cache policy: NSURLRequestReloadIgnoringCacheData
133  Add to back/forward list: NO
134 */
135
136 NSString *WebPageCacheEntryDateKey = @"WebPageCacheEntryDateKey";
137 NSString *WebPageCacheDataSourceKey = @"WebPageCacheDataSourceKey";
138 NSString *WebPageCacheDocumentViewKey = @"WebPageCacheDocumentViewKey";
139
140 @interface NSView (WebFramePluginHosting)
141 - (void)setWebFrame:(WebFrame *)webFrame;
142 @end
143
144 @implementation WebFramePrivate
145
146 - (void)dealloc
147 {
148     [webFrameView release];
149
150     delete scriptDebugger;
151
152     [super dealloc];
153 }
154
155 - (void)finalize
156 {
157     delete scriptDebugger;
158
159     [super finalize];
160 }
161
162 - (void)setWebFrameView:(WebFrameView *)v 
163
164     [v retain];
165     [webFrameView release];
166     webFrameView = v;
167 }
168
169 @end
170
171 CSSStyleDeclaration* core(DOMCSSStyleDeclaration *declaration)
172 {
173     return [declaration _CSSStyleDeclaration];
174 }
175
176 DOMCSSStyleDeclaration *kit(WebCore::CSSStyleDeclaration* declaration)
177 {
178     return [DOMCSSStyleDeclaration _wrapCSSStyleDeclaration:declaration];
179 }
180
181 Element* core(DOMElement *element)
182 {
183     return [element _element];
184 }
185
186 DOMElement *kit(Element* element)
187 {
188     return [DOMElement _wrapElement:element];
189 }
190
191 Node* core(DOMNode *node)
192 {
193     return [node _node];
194 }
195
196 DOMNode *kit(Node* node)
197 {
198     return [DOMNode _wrapNode:node];
199 }
200
201 DOMNode *kit(PassRefPtr<Node> node)
202 {
203     return [DOMNode _wrapNode:node.get()];
204 }
205
206 Document* core(DOMDocument *document)
207 {
208     return [document _document];
209 }
210
211 DOMDocument *kit(Document* document)
212 {
213     return [DOMDocument _wrapDocument:document];
214 }
215
216 HTMLElement* core(DOMHTMLElement *element)
217 {
218     return [element _HTMLElement];
219 }
220
221 DOMHTMLElement *kit(HTMLElement *element)
222 {
223     return [DOMHTMLElement _wrapHTMLElement:element];
224 }
225
226 Range* core(DOMRange *range)
227 {
228     return [range _range];
229 }
230
231 DOMRange *kit(Range* range)
232 {
233     return [DOMRange _wrapRange:range];
234 }
235
236 EditableLinkBehavior core(WebKitEditableLinkBehavior editableLinkBehavior)
237 {
238     switch (editableLinkBehavior) {
239         case WebKitEditableLinkDefaultBehavior:
240             return EditableLinkDefaultBehavior;
241         case WebKitEditableLinkAlwaysLive:
242             return EditableLinkAlwaysLive;
243         case WebKitEditableLinkOnlyLiveWithShiftKey:
244             return EditableLinkOnlyLiveWithShiftKey;
245         case WebKitEditableLinkLiveWhenNotFocused:
246             return EditableLinkLiveWhenNotFocused;
247         case WebKitEditableLinkNeverLive:
248             return EditableLinkNeverLive;
249     }
250     ASSERT_NOT_REACHED();
251     return EditableLinkDefaultBehavior;
252 }
253
254 @implementation WebFrame (WebInternal)
255
256 Frame* core(WebFrame *frame)
257 {
258     return frame ? frame->_private->coreFrame : 0;
259 }
260
261 WebFrame *kit(Frame* frame)
262 {
263     return frame ? static_cast<WebFrameLoaderClient*>(frame->loader()->client())->webFrame() : nil;
264 }
265
266 Page* core(WebView *webView)
267 {
268     return [webView page];
269 }
270
271 WebView *kit(Page* page)
272 {
273     return page ? static_cast<WebChromeClient*>(page->chrome()->client())->webView() : nil;
274 }
275
276 WebView *getWebView(WebFrame *webFrame)
277 {
278     Frame* coreFrame = core(webFrame);
279     if (!coreFrame)
280         return nil;
281     return kit(coreFrame->page());
282 }
283
284 + (PassRefPtr<Frame>)_createFrameWithPage:(Page*)page frameName:(const String&)name frameView:(WebFrameView *)frameView ownerElement:(HTMLFrameOwnerElement*)ownerElement
285 {
286     WebView *webView = kit(page);
287
288     WebFrame *frame = [[self alloc] _initWithWebFrameView:frameView webView:webView];
289     RefPtr<Frame> coreFrame = new Frame(page, ownerElement, new WebFrameLoaderClient(frame));
290     [frame release];
291     frame->_private->coreFrame = coreFrame.get();
292
293     coreFrame->tree()->setName(name);
294     coreFrame->init();
295
296     [webView _setZoomMultiplier:[webView _realZoomMultiplier] isTextOnly:[webView _realZoomMultiplierIsTextOnly]];
297
298     return coreFrame.release();
299 }
300
301 + (void)_createMainFrameWithPage:(Page*)page frameName:(const String&)name frameView:(WebFrameView *)frameView
302 {
303     [self _createFrameWithPage:page frameName:name frameView:frameView ownerElement:0];
304 }
305
306 + (PassRefPtr<WebCore::Frame>)_createSubframeWithOwnerElement:(HTMLFrameOwnerElement*)ownerElement frameName:(const String&)name frameView:(WebFrameView *)frameView
307 {
308     return [self _createFrameWithPage:ownerElement->document()->frame()->page() frameName:name frameView:frameView ownerElement:ownerElement];
309 }
310
311 /*
312     In the case of saving state about a page with frames, we store a tree of items that mirrors the frame tree.  
313     The item that was the target of the user's navigation is designated as the "targetItem".  
314     When this method is called with doClip=YES we're able to create the whole tree except for the target's children, 
315     which will be loaded in the future.  That part of the tree will be filled out as the child loads are committed.
316 */
317
318 + (CFAbsoluteTime)_timeOfLastCompletedLoad
319 {
320     return FrameLoader::timeOfLastCompletedLoad() - kCFAbsoluteTimeIntervalSince1970;
321 }
322
323 - (void)_loadURL:(NSURL *)URL referrer:(NSString *)referrer intoChild:(WebFrame *)childFrame
324 {
325     ASSERT(childFrame);
326     HistoryItem* parentItem = core(self)->loader()->currentHistoryItem();
327     FrameLoadType loadType = [self _frameLoader]->loadType();
328     FrameLoadType childLoadType = FrameLoadTypeRedirectWithLockedHistory;
329
330     // If we're moving in the backforward list, we might want to replace the content
331     // of this child frame with whatever was there at that point.
332     // Reload will maintain the frame contents, LoadSame will not.
333     if (parentItem && parentItem->children().size() &&
334         (isBackForwardLoadType(loadType)
335          || loadType == FrameLoadTypeReload
336          || loadType == FrameLoadTypeReloadAllowingStaleData))
337     {
338         HistoryItem* childItem = parentItem->childItemWithName([childFrame name]);
339         if (childItem) {
340             // Use the original URL to ensure we get all the side-effects, such as
341             // onLoad handlers, of any redirects that happened. An example of where
342             // this is needed is Radar 3213556.
343             URL = [NSURL _web_URLWithDataAsString:childItem->originalURLString()];
344             // These behaviors implied by these loadTypes should apply to the child frames
345             childLoadType = loadType;
346
347             if (isBackForwardLoadType(loadType))
348                 // For back/forward, remember this item so we can traverse any child items as child frames load
349                 core(childFrame)->loader()->setProvisionalHistoryItem(childItem);
350             else
351                 // For reload, just reinstall the current item, since a new child frame was created but we won't be creating a new BF item
352                 core(childFrame)->loader()->setCurrentHistoryItem(childItem);
353         }
354     }
355
356     WebArchive *archive = [[self _dataSource] _popSubframeArchiveWithName:[childFrame name]];
357     if (archive)
358         [childFrame loadArchive:archive];
359     else
360         [childFrame _frameLoader]->load([URL absoluteURL], referrer, childLoadType,
361                                         String(), 0, 0);
362 }
363
364
365 - (void)_viewWillMoveToHostWindow:(NSWindow *)hostWindow
366 {
367     Frame* coreFrame = core(self);
368     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
369         [[[kit(frame) frameView] documentView] viewWillMoveToHostWindow:hostWindow];
370 }
371
372 - (void)_viewDidMoveToHostWindow
373 {
374     Frame* coreFrame = core(self);
375     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
376         [[[kit(frame) frameView] documentView] viewDidMoveToHostWindow];
377 }
378
379 - (void)_addChild:(WebFrame *)child
380 {
381     core(self)->tree()->appendChild(adoptRef(core(child)));
382     if ([child _dataSource])
383         [[child _dataSource] _documentLoader]->setOverrideEncoding([[self _dataSource] _documentLoader]->overrideEncoding());  
384 }
385
386 - (int)_numPendingOrLoadingRequests:(BOOL)recurse
387 {
388     return core(self)->loader()->numPendingOrLoadingRequests(recurse);
389 }
390
391 - (void)_attachScriptDebugger
392 {
393     if (_private->scriptDebugger)
394         return;
395
396     JSGlobalObject* globalObject = core(self)->scriptProxy()->globalObject();
397     if (!globalObject)
398         return;
399
400     _private->scriptDebugger = new WebScriptDebugger(globalObject);
401 }
402
403 - (void)_detachScriptDebugger
404 {
405     if (!_private->scriptDebugger)
406         return;
407
408     delete _private->scriptDebugger;
409     _private->scriptDebugger = 0;
410 }
411
412 - (id)_initWithWebFrameView:(WebFrameView *)fv webView:(WebView *)v
413 {
414     self = [super init];
415     if (!self)
416         return nil;
417
418     _private = [[WebFramePrivate alloc] init];
419
420     if (fv) {
421         [_private setWebFrameView:fv];
422         [fv _setWebFrame:self];
423     }
424
425     _private->shouldCreateRenderers = YES;
426
427     ++WebFrameCount;
428
429     return self;
430 }
431
432 - (NSArray *)_documentViews
433 {
434     NSMutableArray *result = [NSMutableArray array];
435     Frame* coreFrame = core(self);
436     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
437         id docView = [[kit(frame) frameView] documentView];
438         if (docView)
439             [result addObject:docView];
440     }
441     return result;
442 }
443
444 - (void)_updateBackground
445 {
446     BOOL drawsBackground = [getWebView(self) drawsBackground];
447     NSColor *backgroundColor = [getWebView(self) backgroundColor];
448
449     Frame* coreFrame = core(self);
450     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
451         WebFrame *webFrame = kit(frame);
452         // Never call setDrawsBackground:YES here on the scroll view or the background color will
453         // flash between pages loads. setDrawsBackground:YES will be called in _frameLoadCompleted.
454         if (!drawsBackground)
455             [[[webFrame frameView] _scrollView] setDrawsBackground:NO];
456         [[[webFrame frameView] _scrollView] setBackgroundColor:backgroundColor];
457         id documentView = [[webFrame frameView] documentView];
458         if ([documentView respondsToSelector:@selector(setDrawsBackground:)])
459             [documentView setDrawsBackground:drawsBackground];
460         if ([documentView respondsToSelector:@selector(setBackgroundColor:)])
461             [documentView setBackgroundColor:backgroundColor];
462         [self _setDrawsBackground:drawsBackground];
463         [self _setBaseBackgroundColor:backgroundColor];
464     }
465 }
466
467 - (void)_setInternalLoadDelegate:(id)internalLoadDelegate
468 {
469     _private->internalLoadDelegate = internalLoadDelegate;
470 }
471
472 - (id)_internalLoadDelegate
473 {
474     return _private->internalLoadDelegate;
475 }
476
477 #ifndef BUILDING_ON_TIGER
478 - (void)_unmarkAllBadGrammar
479 {
480     Frame* coreFrame = core(self);
481     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
482         Document *doc = frame->document();
483         if (!doc)
484             return;
485
486         doc->removeMarkers(DocumentMarker::Grammar);
487     }
488 }
489 #endif
490
491 - (void)_unmarkAllMisspellings
492 {
493     Frame* coreFrame = core(self);
494     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
495         Document *doc = frame->document();
496         if (!doc)
497             return;
498
499         doc->removeMarkers(DocumentMarker::Spelling);
500     }
501 }
502
503 - (BOOL)_hasSelection
504 {
505     id documentView = [_private->webFrameView documentView];    
506
507     // optimization for common case to avoid creating potentially large selection string
508     if ([documentView isKindOfClass:[WebHTMLView class]])
509         if (Frame* coreFrame = core(self))
510             return coreFrame->selectionController()->isRange();
511
512     if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
513         return [[documentView selectedString] length] > 0;
514     
515     return NO;
516 }
517
518 - (void)_clearSelection
519 {
520     id documentView = [_private->webFrameView documentView];    
521     if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
522         [documentView deselectAll];
523 }
524
525 #if !ASSERT_DISABLED
526 - (BOOL)_atMostOneFrameHasSelection
527 {
528     // FIXME: 4186050 is one known case that makes this debug check fail.
529     BOOL found = NO;
530     Frame* coreFrame = core(self);
531     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
532         if ([kit(frame) _hasSelection]) {
533             if (found)
534                 return NO;
535             found = YES;
536         }
537     return YES;
538 }
539 #endif
540
541 - (WebFrame *)_findFrameWithSelection
542 {
543     Frame* coreFrame = core(self);
544     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
545         if ([kit(frame) _hasSelection])
546             return kit(frame);
547     return nil;
548 }
549
550 - (void)_clearSelectionInOtherFrames
551 {
552     // We rely on WebDocumentSelection protocol implementors to call this method when they become first 
553     // responder. It would be nicer to just notice first responder changes here instead, but there's no 
554     // notification sent when the first responder changes in general (Radar 2573089).
555     WebFrame *frameWithSelection = [[getWebView(self) mainFrame] _findFrameWithSelection];
556     if (frameWithSelection != self)
557         [frameWithSelection _clearSelection];
558
559     // While we're in the general area of selection and frames, check that there is only one now.
560     ASSERT([[getWebView(self) mainFrame] _atMostOneFrameHasSelection]);
561 }
562
563 - (BOOL)_isMainFrame
564 {
565    Frame* coreFrame = core(self);
566    if (!coreFrame)
567        return NO;
568    return coreFrame == coreFrame->page()->mainFrame() ;
569 }
570
571 - (FrameLoader*)_frameLoader
572 {
573     Frame* frame = core(self);
574     return frame ? frame->loader() : 0;
575 }
576
577 static inline WebDataSource *dataSource(DocumentLoader* loader)
578 {
579     return loader ? static_cast<WebDocumentLoaderMac*>(loader)->dataSource() : nil;
580 }
581
582 - (WebDataSource *)_dataSourceForDocumentLoader:(DocumentLoader*)loader
583 {
584     return dataSource(loader);
585 }
586
587 - (void)_addDocumentLoader:(DocumentLoader*)loader toUnarchiveState:(WebArchive *)archive
588 {
589     [dataSource(loader) _addToUnarchiveState:archive];
590 }
591
592 - (WebDataSource *)_dataSource
593 {
594     FrameLoader* frameLoader = [self _frameLoader];
595
596     if (!frameLoader)
597         return nil;
598
599     return dataSource(frameLoader->documentLoader());
600 }
601
602 #if ENABLE(NETSCAPE_PLUGIN_API)
603 - (void)_recursive_resumeNullEventsForAllNetscapePlugins
604 {
605     Frame* coreFrame = core(self);
606     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
607         NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView];
608         if ([documentView isKindOfClass:[WebHTMLView class]])
609             [(WebHTMLView *)documentView _resumeNullEventsForAllNetscapePlugins];
610     }
611 }
612
613 - (void)_recursive_pauseNullEventsForAllNetscapePlugins
614 {
615     Frame* coreFrame = core(self);
616     for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
617         NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView];
618         if ([documentView isKindOfClass:[WebHTMLView class]])
619             [(WebHTMLView *)documentView _pauseNullEventsForAllNetscapePlugins];
620     }
621 }
622 #endif
623
624 static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValue* jsValue)
625 {
626     NSAppleEventDescriptor* aeDesc = 0;
627     switch (jsValue->type()) {
628         case BooleanType:
629             aeDesc = [NSAppleEventDescriptor descriptorWithBoolean:jsValue->getBoolean()];
630             break;
631         case StringType:
632             aeDesc = [NSAppleEventDescriptor descriptorWithString:String(jsValue->getString())];
633             break;
634         case NumberType: {
635             double value = jsValue->getNumber();
636             int intValue = (int)value;
637             if (value == intValue)
638                 aeDesc = [NSAppleEventDescriptor descriptorWithDescriptorType:typeSInt32 bytes:&intValue length:sizeof(intValue)];
639             else
640                 aeDesc = [NSAppleEventDescriptor descriptorWithDescriptorType:typeIEEE64BitFloatingPoint bytes:&value length:sizeof(value)];
641             break;
642         }
643         case ObjectType: {
644             JSObject* object = jsValue->getObject();
645             if (object->inherits(&DateInstance::info)) {
646                 DateInstance* date = static_cast<DateInstance*>(object);
647                 double ms = 0;
648                 int tzOffset = 0;
649                 if (date->getTime(ms, tzOffset)) {
650                     CFAbsoluteTime utcSeconds = ms / 1000 - kCFAbsoluteTimeIntervalSince1970;
651                     LongDateTime ldt;
652                     if (noErr == UCConvertCFAbsoluteTimeToLongDateTime(utcSeconds, &ldt))
653                         aeDesc = [NSAppleEventDescriptor descriptorWithDescriptorType:typeLongDateTime bytes:&ldt length:sizeof(ldt)];
654                 }
655             }
656             else if (object->inherits(&ArrayInstance::info)) {
657                 static HashSet<JSObject*> visitedElems;
658                 if (!visitedElems.contains(object)) {
659                     visitedElems.add(object);
660                     
661                     ArrayInstance* array = static_cast<ArrayInstance*>(object);
662                     aeDesc = [NSAppleEventDescriptor listDescriptor];
663                     unsigned numItems = array->getLength();
664                     for (unsigned i = 0; i < numItems; ++i)
665                         [aeDesc insertDescriptor:aeDescFromJSValue(exec, array->getItem(i)) atIndex:0];
666                     
667                     visitedElems.remove(object);
668                 }
669             }
670             if (!aeDesc) {
671                 JSValue* primitive = object->toPrimitive(exec);
672                 if (exec->hadException()) {
673                     exec->clearException();
674                     return [NSAppleEventDescriptor nullDescriptor];
675                 }
676                 return aeDescFromJSValue(exec, primitive);
677             }
678             break;
679         }
680         case UndefinedType:
681             aeDesc = [NSAppleEventDescriptor descriptorWithTypeCode:cMissingValue];
682             break;
683         default:
684             LOG_ERROR("Unknown JavaScript type: %d", jsValue->type());
685             // no break;
686         case UnspecifiedType:
687         case NullType:
688         case GetterSetterType:
689             aeDesc = [NSAppleEventDescriptor nullDescriptor];
690             break;
691     }
692     
693     return aeDesc;
694 }
695
696 - (NSString *)_domain
697 {
698     Document *doc = _private->coreFrame->document();
699     if (doc)
700         return doc->domain();
701     return nil;
702 }
703
704 - (void)_addData:(NSData *)data
705 {
706     Document *doc = _private->coreFrame->document();
707     
708     // Document may be nil if the part is about to redirect
709     // as a result of JS executing during load, i.e. one frame
710     // changing another's location before the frame's document
711     // has been created. 
712     if (doc) {
713         doc->setShouldCreateRenderers(_private->shouldCreateRenderers);
714         _private->coreFrame->loader()->addData((const char *)[data bytes], [data length]);
715     }
716 }
717
718 - (NSString *)_stringWithDocumentTypeStringAndMarkupString:(NSString *)markupString
719 {
720     return _private->coreFrame->documentTypeString() + markupString;
721 }
722
723 - (NSArray *)_nodesFromList:(Vector<Node*> *)nodesVector
724 {
725     size_t size = nodesVector->size();
726     NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:size];
727     for (size_t i = 0; i < size; ++i)
728         [nodes addObject:[DOMNode _wrapNode:(*nodesVector)[i]]];
729     return nodes;
730 }
731
732 - (NSString *)_markupStringFromNode:(DOMNode *)node nodes:(NSArray **)nodes
733 {
734     // FIXME: This is never "for interchange". Is that right? See the next method.
735     Vector<Node*> nodeList;
736     NSString *markupString = createMarkup([node _node], IncludeNode, nodes ? &nodeList : 0);
737     if (nodes)
738         *nodes = [self _nodesFromList:&nodeList];
739
740     return [self _stringWithDocumentTypeStringAndMarkupString:markupString];
741 }
742
743 - (NSString *)_markupStringFromRange:(DOMRange *)range nodes:(NSArray **)nodes
744 {
745     // FIXME: This is always "for interchange". Is that right? See the previous method.
746     Vector<Node*> nodeList;
747     NSString *markupString = createMarkup([range _range], nodes ? &nodeList : 0, AnnotateForInterchange);
748     if (nodes)
749         *nodes = [self _nodesFromList:&nodeList];
750
751     return [self _stringWithDocumentTypeStringAndMarkupString:markupString];
752 }
753
754 - (NSString *)_selectedString
755 {
756     String text = _private->coreFrame->selectedText();
757     text.replace('\\', _private->coreFrame->backslashAsCurrencySymbol());
758     return text;
759 }
760
761 - (NSString *)_stringForRange:(DOMRange *)range
762 {
763     // This will give a system malloc'd buffer that can be turned directly into an NSString
764     unsigned length;
765     UChar* buf = plainTextToMallocAllocatedBuffer([range _range], length);
766     
767     if (!buf)
768         return [NSString string];
769     
770     UChar backslashAsCurrencySymbol = _private->coreFrame->backslashAsCurrencySymbol();
771     if (backslashAsCurrencySymbol != '\\')
772         for (unsigned n = 0; n < length; n++) 
773             if (buf[n] == '\\')
774                 buf[n] = backslashAsCurrencySymbol;
775
776     // Transfer buffer ownership to NSString
777     return [[[NSString alloc] initWithCharactersNoCopy:buf length:length freeWhenDone:YES] autorelease];
778 }
779
780 - (void)_forceLayoutAdjustingViewSize:(BOOL)flag
781 {
782     _private->coreFrame->forceLayout(!flag);
783     if (flag)
784         _private->coreFrame->view()->adjustViewSize();
785 }
786
787 - (void)_forceLayoutWithMinimumPageWidth:(float)minPageWidth maximumPageWidth:(float)maxPageWidth adjustingViewSize:(BOOL)flag
788 {
789     _private->coreFrame->forceLayoutWithPageWidthRange(minPageWidth, maxPageWidth, flag);
790 }
791
792 - (void)_sendScrollEvent
793 {
794     _private->coreFrame->sendScrollEvent();
795 }
796
797 - (void)_drawRect:(NSRect)rect
798 {
799     PlatformGraphicsContext* platformContext = static_cast<PlatformGraphicsContext*>([[NSGraphicsContext currentContext] graphicsPort]);
800     ASSERT([[NSGraphicsContext currentContext] isFlipped]);
801     GraphicsContext context(platformContext);
802     
803     _private->coreFrame->paint(&context, enclosingIntRect(rect));
804 }
805
806 // Used by pagination code called from AppKit when a standalone web page is printed.
807 - (NSArray*)_computePageRectsWithPrintWidthScaleFactor:(float)printWidthScaleFactor printHeight:(float)printHeight
808 {
809     NSMutableArray* pages = [NSMutableArray arrayWithCapacity:5];
810     if (printWidthScaleFactor <= 0) {
811         LOG_ERROR("printWidthScaleFactor has bad value %.2f", printWidthScaleFactor);
812         return pages;
813     }
814     
815     if (printHeight <= 0) {
816         LOG_ERROR("printHeight has bad value %.2f", printHeight);
817         return pages;
818     }
819
820     if (!_private->coreFrame || !_private->coreFrame->document() || !_private->coreFrame->view()) return pages;
821     RenderView* root = static_cast<RenderView *>(_private->coreFrame->document()->renderer());
822     if (!root) return pages;
823     
824     FrameView* view = _private->coreFrame->view();
825     if (!view)
826         return pages;
827
828     NSView* documentView = view->documentView();
829     if (!documentView)
830         return pages;
831
832     float currPageHeight = printHeight;
833     float docHeight = root->layer()->height();
834     float docWidth = root->layer()->width();
835     float printWidth = docWidth/printWidthScaleFactor;
836     
837     // We need to give the part the opportunity to adjust the page height at each step.
838     for (float i = 0; i < docHeight; i += currPageHeight) {
839         float proposedBottom = min(docHeight, i + printHeight);
840         _private->coreFrame->adjustPageHeight(&proposedBottom, i, proposedBottom, i);
841         currPageHeight = max(1.0f, proposedBottom - i);
842         for (float j = 0; j < docWidth; j += printWidth) {
843             NSValue* val = [NSValue valueWithRect: NSMakeRect(j, i, printWidth, currPageHeight)];
844             [pages addObject: val];
845         }
846     }
847     
848     return pages;
849 }
850
851 // This is to support the case where a webview is embedded in the view that's being printed
852 - (void)_adjustPageHeightNew:(float *)newBottom top:(float)oldTop bottom:(float)oldBottom limit:(float)bottomLimit
853 {
854     _private->coreFrame->adjustPageHeight(newBottom, oldTop, oldBottom, bottomLimit);
855 }
856
857 - (NSObject *)_copyRenderNode:(RenderObject *)node copier:(id <WebCoreRenderTreeCopier>)copier
858 {
859     NSMutableArray *children = [[NSMutableArray alloc] init];
860     for (RenderObject *child = node->firstChild(); child; child = child->nextSibling()) {
861         [children addObject:[self _copyRenderNode:child copier:copier]];
862     }
863           
864     NSString *name = [[NSString alloc] initWithUTF8String:node->renderName()];
865     
866     RenderWidget* renderWidget = node->isWidget() ? static_cast<RenderWidget*>(node) : 0;
867     Widget* widget = renderWidget ? renderWidget->widget() : 0;
868     NSView *view = widget ? widget->getView() : nil;
869     
870     int nx, ny;
871     node->absolutePosition(nx, ny);
872     NSObject *copiedNode = [copier nodeWithName:name
873                                        position:NSMakePoint(nx,ny)
874                                            rect:NSMakeRect(node->xPos(), node->yPos(), node->width(), node->height())
875                                            view:view
876                                        children:children];
877     
878     [name release];
879     [children release];
880     
881     return copiedNode;
882 }
883
884 - (NSObject *)_copyRenderTree:(id <WebCoreRenderTreeCopier>)copier
885 {
886     RenderObject *renderer = _private->coreFrame->renderer();
887     if (!renderer) {
888         return nil;
889     }
890     return [self _copyRenderNode:renderer copier:copier];
891 }
892
893 static HTMLInputElement* inputElementFromDOMElement(DOMElement* element)
894 {
895     Node* node = [element _node];
896     if (node->hasTagName(inputTag))
897         return static_cast<HTMLInputElement*>(node);
898     return nil;
899 }
900
901 static HTMLFormElement *formElementFromDOMElement(DOMElement *element)
902 {
903     Node *node = [element _node];
904     // This should not be necessary, but an XSL file on
905     // maps.google.com crashes otherwise because it is an xslt file
906     // that contains <form> elements that aren't in any namespace, so
907     // they come out as generic CML elements
908     if (node && node->hasTagName(formTag)) {
909         return static_cast<HTMLFormElement *>(node);
910     }
911     return nil;
912 }
913
914 - (DOMElement *)_elementWithName:(NSString *)name inForm:(DOMElement *)form
915 {
916     HTMLFormElement *formElement = formElementFromDOMElement(form);
917     if (formElement) {
918         Vector<HTMLGenericFormElement*>& elements = formElement->formElements;
919         AtomicString targetName = name;
920         for (unsigned int i = 0; i < elements.size(); i++) {
921             HTMLGenericFormElement *elt = elements[i];
922             // Skip option elements, other duds
923             if (elt->name() == targetName)
924                 return [DOMElement _wrapElement:elt];
925         }
926     }
927     return nil;
928 }
929
930 - (BOOL)_elementDoesAutoComplete:(DOMElement *)element
931 {
932     HTMLInputElement *inputElement = inputElementFromDOMElement(element);
933     return inputElement != nil
934         && inputElement->inputType() == HTMLInputElement::TEXT
935         && inputElement->autoComplete();
936 }
937
938 - (BOOL)_elementIsPassword:(DOMElement *)element
939 {
940     HTMLInputElement *inputElement = inputElementFromDOMElement(element);
941     return inputElement != nil
942         && inputElement->inputType() == HTMLInputElement::PASSWORD;
943 }
944
945 - (DOMElement *)_formForElement:(DOMElement *)element;
946 {
947     HTMLInputElement *inputElement = inputElementFromDOMElement(element);
948     if (inputElement) {
949         HTMLFormElement *formElement = inputElement->form();
950         if (formElement) {
951             return [DOMElement _wrapElement:formElement];
952         }
953     }
954     return nil;
955 }
956
957 - (DOMElement *)_currentForm
958 {
959     return [DOMElement _wrapElement:_private->coreFrame->currentForm()];
960 }
961
962 - (NSArray *)_controlsInForm:(DOMElement *)form
963 {
964     NSMutableArray *results = nil;
965     HTMLFormElement *formElement = formElementFromDOMElement(form);
966     if (formElement) {
967         Vector<HTMLGenericFormElement*>& elements = formElement->formElements;
968         for (unsigned int i = 0; i < elements.size(); i++) {
969             if (elements.at(i)->isEnumeratable()) { // Skip option elements, other duds
970                 DOMElement *de = [DOMElement _wrapElement:elements.at(i)];
971                 if (!results) {
972                     results = [NSMutableArray arrayWithObject:de];
973                 } else {
974                     [results addObject:de];
975                 }
976             }
977         }
978     }
979     return results;
980 }
981
982 - (NSString *)_searchForLabels:(NSArray *)labels beforeElement:(DOMElement *)element
983 {
984     return _private->coreFrame->searchForLabelsBeforeElement(labels, [element _element]);
985 }
986
987 - (NSString *)_matchLabels:(NSArray *)labels againstElement:(DOMElement *)element
988 {
989     return _private->coreFrame->matchLabelsAgainstElement(labels, [element _element]);
990 }
991
992 - (NSURL *)_URLWithAttributeString:(NSString *)string
993 {
994     Document* doc = _private->coreFrame->document();
995     if (!doc)
996         return nil;
997     // FIXME: is parseURL appropriate here?
998     return doc->completeURL(parseURL(string));
999 }
1000
1001 - (BOOL)_searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag startInSelection:(BOOL)startInSelection
1002 {
1003     return _private->coreFrame->findString(string, forward, caseFlag, wrapFlag, startInSelection);
1004 }
1005
1006 - (unsigned)_markAllMatchesForText:(NSString *)string caseSensitive:(BOOL)caseFlag limit:(unsigned)limit
1007 {
1008     return _private->coreFrame->markAllMatchesForText(string, caseFlag, limit);
1009 }
1010
1011 - (BOOL)_markedTextMatchesAreHighlighted
1012 {
1013     return _private->coreFrame->markedTextMatchesAreHighlighted();
1014 }
1015
1016 - (void)_setMarkedTextMatchesAreHighlighted:(BOOL)doHighlight
1017 {
1018     _private->coreFrame->setMarkedTextMatchesAreHighlighted(doHighlight);
1019 }
1020
1021 - (void)_unmarkAllTextMatches
1022 {
1023     Document *doc = _private->coreFrame->document();
1024     if (!doc) {
1025         return;
1026     }
1027     doc->removeMarkers(DocumentMarker::TextMatch);
1028 }
1029
1030 - (NSArray *)_rectsForTextMatches
1031 {
1032     Document *doc = _private->coreFrame->document();
1033     if (!doc)
1034         return [NSArray array];
1035     
1036     NSMutableArray *result = [NSMutableArray array];
1037     Vector<IntRect> rects = doc->renderedRectsForMarkers(DocumentMarker::TextMatch);
1038     unsigned count = rects.size();
1039     for (unsigned index = 0; index < count; ++index)
1040         [result addObject:[NSValue valueWithRect:rects[index]]];
1041     
1042     return result;
1043 }
1044
1045 - (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string
1046 {
1047     return [self _stringByEvaluatingJavaScriptFromString:string forceUserGesture:true];
1048 }
1049
1050 - (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string forceUserGesture:(BOOL)forceUserGesture
1051 {
1052     ASSERT(_private->coreFrame->document());
1053     
1054     JSValue* result = _private->coreFrame->loader()->executeScript(string, forceUserGesture);
1055
1056     if (!_private->coreFrame) // In case the script removed our frame from the page.
1057         return @"";
1058
1059     // This bizarre set of rules matches behavior from WebKit for Safari 2.0.
1060     // If you don't like it, use -[WebScriptObject evaluateWebScript:] or 
1061     // JSEvaluateScript instead, since they have less surprising semantics.
1062     if (!result || !result->isBoolean() && !result->isString() && !result->isNumber())
1063         return @"";
1064
1065     JSLock lock;
1066     return String(result->toString(_private->coreFrame->scriptProxy()->globalObject()->globalExec()));
1067 }
1068
1069 - (NSAppleEventDescriptor *)_aeDescByEvaluatingJavaScriptFromString:(NSString *)string
1070 {
1071     ASSERT(_private->coreFrame->document());
1072     ASSERT(_private->coreFrame == _private->coreFrame->page()->mainFrame());
1073     JSValue* result = _private->coreFrame->loader()->executeScript(string, true);
1074     if (!result) // FIXME: pass errors
1075         return 0;
1076     JSLock lock;
1077     return aeDescFromJSValue(_private->coreFrame->scriptProxy()->globalObject()->globalExec(), result);
1078 }
1079
1080 - (NSRect)_caretRectAtNode:(DOMNode *)node offset:(int)offset affinity:(NSSelectionAffinity)affinity
1081 {
1082     return [node _node]->renderer()->caretRect(offset, static_cast<EAffinity>(affinity));
1083 }
1084
1085 - (NSRect)_firstRectForDOMRange:(DOMRange *)range
1086 {
1087    return _private->coreFrame->firstRectForRange([range _range]);
1088 }
1089
1090 - (void)_scrollDOMRangeToVisible:(DOMRange *)range
1091 {
1092     NSRect rangeRect = [self _firstRectForDOMRange:range];    
1093     Node *startNode = [[range startContainer] _node];
1094         
1095     if (startNode && startNode->renderer()) {
1096         RenderLayer *layer = startNode->renderer()->enclosingLayer();
1097         if (layer)
1098             layer->scrollRectToVisible(enclosingIntRect(rangeRect), RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignToEdgeIfNeeded);
1099     }
1100 }
1101
1102 - (NSURL *)_baseURL
1103 {
1104     return _private->coreFrame->document()->baseURL();
1105 }
1106
1107 - (NSString *)_stringWithData:(NSData *)data
1108 {
1109     Document* doc = _private->coreFrame->document();
1110     if (!doc)
1111         return nil;
1112     TextResourceDecoder* decoder = doc->decoder();
1113     if (!decoder)
1114         return nil;
1115     return decoder->encoding().decode(reinterpret_cast<const char*>([data bytes]), [data length]);
1116 }
1117
1118 + (NSString *)_stringWithData:(NSData *)data textEncodingName:(NSString *)textEncodingName
1119 {
1120     WebCore::TextEncoding encoding(textEncodingName);
1121     if (!encoding.isValid())
1122         encoding = WindowsLatin1Encoding();
1123     return encoding.decode(reinterpret_cast<const char*>([data bytes]), [data length]);
1124 }
1125
1126 - (BOOL)_needsLayout
1127 {
1128     return _private->coreFrame->view() ? _private->coreFrame->view()->needsLayout() : false;
1129 }
1130
1131 - (NSString *)_renderTreeAsExternalRepresentation
1132 {
1133     return externalRepresentation(_private->coreFrame->renderer());
1134 }
1135
1136 - (id)_accessibilityTree
1137 {
1138     AXObjectCache::enableAccessibility();
1139     if (!_private->coreFrame || !_private->coreFrame->document())
1140         return nil;
1141     RenderView* root = static_cast<RenderView *>(_private->coreFrame->document()->renderer());
1142     if (!root)
1143         return nil;
1144     return _private->coreFrame->document()->axObjectCache()->get(root);
1145 }
1146
1147 - (void)_setBaseBackgroundColor:(NSColor *)backgroundColor
1148 {
1149     if (_private->coreFrame && _private->coreFrame->view()) {
1150         Color color = colorFromNSColor([backgroundColor colorUsingColorSpaceName:NSDeviceRGBColorSpace]);
1151         _private->coreFrame->view()->setBaseBackgroundColor(color);
1152     }
1153 }
1154
1155 - (void)_setDrawsBackground:(BOOL)drawsBackground
1156 {
1157     if (_private->coreFrame && _private->coreFrame->view())
1158         _private->coreFrame->view()->setTransparent(!drawsBackground);
1159 }
1160
1161 - (DOMRange *)_rangeByAlteringCurrentSelection:(SelectionController::EAlteration)alteration direction:(SelectionController::EDirection)direction granularity:(TextGranularity)granularity
1162 {
1163     if (_private->coreFrame->selectionController()->isNone())
1164         return nil;
1165
1166     SelectionController selectionController;
1167     selectionController.setSelection(_private->coreFrame->selectionController()->selection());
1168     selectionController.modify(alteration, direction, granularity);
1169     return [DOMRange _wrapRange:selectionController.toRange().get()];
1170 }
1171
1172 - (TextGranularity)_selectionGranularity
1173 {
1174     return _private->coreFrame->selectionGranularity();
1175 }
1176
1177 - (NSRange)_convertToNSRange:(Range *)range
1178 {
1179     if (!range || !range->startContainer())
1180         return NSMakeRange(NSNotFound, 0);
1181
1182     Element* selectionRoot = _private->coreFrame->selectionController()->rootEditableElement();
1183     Element* scope = selectionRoot ? selectionRoot : _private->coreFrame->document()->documentElement();
1184     
1185     // Mouse events may cause TSM to attempt to create an NSRange for a portion of the view
1186     // that is not inside the current editable region.  These checks ensure we don't produce
1187     // potentially invalid data when responding to such requests.
1188     if (range->startContainer() != scope && !range->startContainer()->isDescendantOf(scope))
1189         return NSMakeRange(NSNotFound, 0);
1190     if (range->endContainer() != scope && !range->endContainer()->isDescendantOf(scope))
1191         return NSMakeRange(NSNotFound, 0);
1192     
1193     RefPtr<Range> testRange = Range::create(scope->document(), scope, 0, range->startContainer(), range->startOffset());
1194     ASSERT(testRange->startContainer() == scope);
1195     int startPosition = TextIterator::rangeLength(testRange.get());
1196
1197     ExceptionCode ec;
1198     testRange->setEnd(range->endContainer(), range->endOffset(), ec);
1199     ASSERT(testRange->startContainer() == scope);
1200     int endPosition = TextIterator::rangeLength(testRange.get());
1201
1202     return NSMakeRange(startPosition, endPosition - startPosition);
1203 }
1204
1205 - (PassRefPtr<Range>)_convertToDOMRange:(NSRange)nsrange
1206 {
1207     if (nsrange.location > INT_MAX)
1208         return 0;
1209     if (nsrange.length > INT_MAX || nsrange.location + nsrange.length > INT_MAX)
1210         nsrange.length = INT_MAX - nsrange.location;
1211
1212     // our critical assumption is that we are only called by input methods that
1213     // concentrate on a given area containing the selection
1214     // We have to do this because of text fields and textareas. The DOM for those is not
1215     // directly in the document DOM, so serialization is problematic. Our solution is
1216     // to use the root editable element of the selection start as the positional base.
1217     // That fits with AppKit's idea of an input context.
1218     Element* selectionRoot = _private->coreFrame->selectionController()->rootEditableElement();
1219     Element* scope = selectionRoot ? selectionRoot : _private->coreFrame->document()->documentElement();
1220     return TextIterator::rangeFromLocationAndLength(scope, nsrange.location, nsrange.length);
1221 }
1222
1223 - (DOMRange *)_convertNSRangeToDOMRange:(NSRange)nsrange
1224 {
1225     return [DOMRange _wrapRange:[self _convertToDOMRange:nsrange].get()];
1226 }
1227
1228 - (NSRange)_convertDOMRangeToNSRange:(DOMRange *)range
1229 {
1230     return [self _convertToNSRange:[range _range]];
1231 }
1232
1233 - (DOMRange *)_markDOMRange
1234 {
1235     return [DOMRange _wrapRange:_private->coreFrame->mark().toRange().get()];
1236 }
1237
1238 - (NSRange)_markedTextNSRange
1239 {
1240     return [self _convertToNSRange:_private->coreFrame->editor()->compositionRange().get()];
1241 }
1242
1243 // Given proposedRange, returns an extended range that includes adjacent whitespace that should
1244 // be deleted along with the proposed range in order to preserve proper spacing and punctuation of
1245 // the text surrounding the deletion.
1246 - (DOMRange *)_smartDeleteRangeForProposedRange:(DOMRange *)proposedRange
1247 {
1248     Node *startContainer = [[proposedRange startContainer] _node];
1249     Node *endContainer = [[proposedRange endContainer] _node];
1250     if (startContainer == nil || endContainer == nil)
1251         return nil;
1252
1253     ASSERT(startContainer->document() == endContainer->document());
1254     
1255     _private->coreFrame->document()->updateLayoutIgnorePendingStylesheets();
1256
1257     Position start(startContainer, [proposedRange startOffset]);
1258     Position end(endContainer, [proposedRange endOffset]);
1259     Position newStart = start.upstream().leadingWhitespacePosition(DOWNSTREAM, true);
1260     if (newStart.isNull())
1261         newStart = start;
1262     Position newEnd = end.downstream().trailingWhitespacePosition(DOWNSTREAM, true);
1263     if (newEnd.isNull())
1264         newEnd = end;
1265
1266     newStart = rangeCompliantEquivalent(newStart);
1267     newEnd = rangeCompliantEquivalent(newEnd);
1268
1269     RefPtr<Range> range = _private->coreFrame->document()->createRange();
1270     int exception = 0;
1271     range->setStart(newStart.node(), newStart.offset(), exception);
1272     range->setEnd(newStart.node(), newStart.offset(), exception);
1273     return [DOMRange _wrapRange:range.get()];
1274 }
1275
1276 // Determines whether whitespace needs to be added around aString to preserve proper spacing and
1277 // punctuation when it‚Äôs inserted into the receiver‚Äôs text over charRange. Returns by reference
1278 // in beforeString and afterString any whitespace that should be added, unless either or both are
1279 // nil. Both are returned as nil if aString is nil or if smart insertion and deletion are disabled.
1280 - (void)_smartInsertForString:(NSString *)pasteString replacingRange:(DOMRange *)rangeToReplace beforeString:(NSString **)beforeString afterString:(NSString **)afterString
1281 {
1282     // give back nil pointers in case of early returns
1283     if (beforeString)
1284         *beforeString = nil;
1285     if (afterString)
1286         *afterString = nil;
1287         
1288     // inspect destination
1289     Node *startContainer = [[rangeToReplace startContainer] _node];
1290     Node *endContainer = [[rangeToReplace endContainer] _node];
1291
1292     Position startPos(startContainer, [rangeToReplace startOffset]);
1293     Position endPos(endContainer, [rangeToReplace endOffset]);
1294
1295     VisiblePosition startVisiblePos = VisiblePosition(startPos, VP_DEFAULT_AFFINITY);
1296     VisiblePosition endVisiblePos = VisiblePosition(endPos, VP_DEFAULT_AFFINITY);
1297     
1298     // this check also ensures startContainer, startPos, endContainer, and endPos are non-null
1299     if (startVisiblePos.isNull() || endVisiblePos.isNull())
1300         return;
1301
1302     bool addLeadingSpace = startPos.leadingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isStartOfParagraph(startVisiblePos);
1303     if (addLeadingSpace)
1304         if (UChar previousChar = startVisiblePos.previous().characterAfter())
1305             addLeadingSpace = !isCharacterSmartReplaceExempt(previousChar, true);
1306     
1307     bool addTrailingSpace = endPos.trailingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isEndOfParagraph(endVisiblePos);
1308     if (addTrailingSpace)
1309         if (UChar thisChar = endVisiblePos.characterAfter())
1310             addTrailingSpace = !isCharacterSmartReplaceExempt(thisChar, false);
1311     
1312     // inspect source
1313     bool hasWhitespaceAtStart = false;
1314     bool hasWhitespaceAtEnd = false;
1315     unsigned pasteLength = [pasteString length];
1316     if (pasteLength > 0) {
1317         NSCharacterSet *whiteSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
1318         
1319         if ([whiteSet characterIsMember:[pasteString characterAtIndex:0]]) {
1320             hasWhitespaceAtStart = YES;
1321         }
1322         if ([whiteSet characterIsMember:[pasteString characterAtIndex:(pasteLength - 1)]]) {
1323             hasWhitespaceAtEnd = YES;
1324         }
1325     }
1326     
1327     // issue the verdict
1328     if (beforeString && addLeadingSpace && !hasWhitespaceAtStart)
1329         *beforeString = @" ";
1330     if (afterString && addTrailingSpace && !hasWhitespaceAtEnd)
1331         *afterString = @" ";
1332 }
1333
1334 - (DOMDocumentFragment *)_documentFragmentWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString 
1335 {
1336     if (!_private->coreFrame || !_private->coreFrame->document())
1337         return 0;
1338
1339     return [DOMDocumentFragment _wrapDocumentFragment:createFragmentFromMarkup(_private->coreFrame->document(), markupString, baseURLString).get()];
1340 }
1341
1342 - (DOMDocumentFragment *)_documentFragmentWithText:(NSString *)text inContext:(DOMRange *)context
1343 {
1344     return [DOMDocumentFragment _wrapDocumentFragment:createFragmentFromText([context _range], text).get()];
1345 }
1346
1347 - (DOMDocumentFragment *)_documentFragmentWithNodesAsParagraphs:(NSArray *)nodes
1348 {
1349     if (!_private->coreFrame || !_private->coreFrame->document())
1350         return 0;
1351     
1352     NSEnumerator *nodeEnum = [nodes objectEnumerator];
1353     Vector<Node*> nodesVector;
1354     DOMNode *node;
1355     while ((node = [nodeEnum nextObject]))
1356         nodesVector.append([node _node]);
1357     
1358     return [DOMDocumentFragment _wrapDocumentFragment:createFragmentFromNodes(_private->coreFrame->document(), nodesVector).get()];
1359 }
1360
1361 - (void)_replaceSelectionWithFragment:(DOMDocumentFragment *)fragment selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle
1362 {
1363     if (_private->coreFrame->selectionController()->isNone() || !fragment)
1364         return;
1365     
1366     applyCommand(new ReplaceSelectionCommand(_private->coreFrame->document(), [fragment _documentFragment], selectReplacement, smartReplace, matchStyle));
1367     _private->coreFrame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded);
1368 }
1369
1370 - (void)_replaceSelectionWithNode:(DOMNode *)node selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle
1371 {
1372     DOMDocumentFragment *fragment = [DOMDocumentFragment _wrapDocumentFragment:_private->coreFrame->document()->createDocumentFragment().get()];
1373     [fragment appendChild:node];
1374     [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:matchStyle];
1375 }
1376
1377 - (void)_replaceSelectionWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1378 {
1379     DOMDocumentFragment *fragment = [self _documentFragmentWithMarkupString:markupString baseURLString:baseURLString];
1380     [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:NO];
1381 }
1382
1383 - (void)_replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1384 {
1385     [self _replaceSelectionWithFragment:[self _documentFragmentWithText:text
1386         inContext:[DOMRange _wrapRange:_private->coreFrame->selectionController()->toRange().get()]]
1387         selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:YES];
1388 }
1389
1390 - (void)_insertParagraphSeparatorInQuotedContent
1391 {
1392     if (_private->coreFrame->selectionController()->isNone())
1393         return;
1394     
1395     TypingCommand::insertParagraphSeparatorInQuotedContent(_private->coreFrame->document());
1396     _private->coreFrame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded);
1397 }
1398
1399 - (VisiblePosition)_visiblePositionForPoint:(NSPoint)point
1400 {
1401     IntPoint outerPoint(point);
1402     HitTestResult result = _private->coreFrame->eventHandler()->hitTestResultAtPoint(outerPoint, true);
1403     Node* node = result.innerNode();
1404     if (!node)
1405         return VisiblePosition();
1406     RenderObject* renderer = node->renderer();
1407     if (!renderer)
1408         return VisiblePosition();
1409     VisiblePosition visiblePos = renderer->positionForCoordinates(result.localPoint().x(), result.localPoint().y());
1410     if (visiblePos.isNull())
1411         visiblePos = VisiblePosition(Position(node, 0));
1412     return visiblePos;
1413 }
1414
1415 - (DOMRange *)_characterRangeAtPoint:(NSPoint)point
1416 {
1417     VisiblePosition position = [self _visiblePositionForPoint:point];
1418     if (position.isNull())
1419         return nil;
1420     
1421     VisiblePosition previous = position.previous();
1422     if (previous.isNotNull()) {
1423         DOMRange *previousCharacterRange = [DOMRange _wrapRange:makeRange(previous, position).get()];
1424         NSRect rect = [self _firstRectForDOMRange:previousCharacterRange];
1425         if (NSPointInRect(point, rect))
1426             return previousCharacterRange;
1427     }
1428
1429     VisiblePosition next = position.next();
1430     if (next.isNotNull()) {
1431         DOMRange *nextCharacterRange = [DOMRange _wrapRange:makeRange(position, next).get()];
1432         NSRect rect = [self _firstRectForDOMRange:nextCharacterRange];
1433         if (NSPointInRect(point, rect))
1434             return nextCharacterRange;
1435     }
1436     
1437     return nil;
1438 }
1439
1440 - (DOMCSSStyleDeclaration *)_typingStyle
1441 {
1442     if (!_private->coreFrame || !_private->coreFrame->typingStyle())
1443         return nil;
1444     return [DOMCSSStyleDeclaration _wrapCSSStyleDeclaration:_private->coreFrame->typingStyle()->copy().get()];
1445 }
1446
1447 - (void)_setTypingStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(EditAction)undoAction
1448 {
1449     if (!_private->coreFrame)
1450         return;
1451     _private->coreFrame->computeAndSetTypingStyle([style _CSSStyleDeclaration], undoAction);
1452 }
1453
1454 - (NSFont *)_fontForSelection:(BOOL *)hasMultipleFonts
1455 {
1456     bool multipleFonts = false;
1457     NSFont *font = nil;
1458     if (_private->coreFrame) {
1459         const SimpleFontData* fd = _private->coreFrame->editor()->fontForSelection(multipleFonts);
1460         if (fd)
1461             font = fd->getNSFont();
1462     }
1463     
1464     if (hasMultipleFonts)
1465         *hasMultipleFonts = multipleFonts;
1466     return font;
1467 }
1468
1469 - (void)_dragSourceMovedTo:(NSPoint)windowLoc
1470 {
1471     if (!_private->coreFrame)
1472         return;
1473     FrameView* view = _private->coreFrame->view();
1474     if (!view)
1475         return;
1476     // FIXME: These are fake modifier keys here, but they should be real ones instead.
1477     PlatformMouseEvent event(IntPoint(windowLoc), globalPoint(windowLoc, [view->getView() window]),
1478         LeftButton, MouseEventMoved, 0, false, false, false, false, currentTime());
1479     _private->coreFrame->eventHandler()->dragSourceMovedTo(event);
1480 }
1481
1482 - (void)_dragSourceEndedAt:(NSPoint)windowLoc operation:(NSDragOperation)operation
1483 {
1484     if (!_private->coreFrame)
1485         return;
1486     FrameView* view = _private->coreFrame->view();
1487     if (!view)
1488         return;
1489     // FIXME: These are fake modifier keys here, but they should be real ones instead.
1490     PlatformMouseEvent event(IntPoint(windowLoc), globalPoint(windowLoc, [view->getView() window]),
1491         LeftButton, MouseEventMoved, 0, false, false, false, false, currentTime());
1492     _private->coreFrame->eventHandler()->dragSourceEndedAt(event, (DragOperation)operation);
1493 }
1494
1495 - (BOOL)_getData:(NSData **)data andResponse:(NSURLResponse **)response forURL:(NSString *)url
1496 {
1497     Document* doc = _private->coreFrame->document();
1498     if (!doc)
1499         return NO;
1500
1501     CachedResource* resource = doc->docLoader()->cachedResource(url);
1502     if (!resource)
1503         return NO;
1504
1505     SharedBuffer* buffer = resource->data();
1506     if (buffer)
1507         *data = [buffer->createNSData() autorelease];
1508     else
1509         *data = nil;
1510
1511     *response = resource->response().nsURLResponse();
1512     return YES;
1513 }
1514
1515 - (void)_getAllResourceDatas:(NSArray **)datas andResponses:(NSArray **)responses
1516 {
1517     Document* doc = _private->coreFrame->document();
1518     if (!doc) {
1519         NSArray* emptyArray = [NSArray array];
1520         *datas = emptyArray;
1521         *responses = emptyArray;
1522         return;
1523     }
1524
1525     const HashMap<String, CachedResource*>& allResources = doc->docLoader()->allCachedResources();
1526
1527     NSMutableArray *d = [[NSMutableArray alloc] initWithCapacity:allResources.size()];
1528     NSMutableArray *r = [[NSMutableArray alloc] initWithCapacity:allResources.size()];
1529
1530     HashMap<String, CachedResource*>::const_iterator end = allResources.end();
1531     for (HashMap<String, CachedResource*>::const_iterator it = allResources.begin(); it != end; ++it) {
1532         SharedBuffer* buffer = it->second->data();
1533         NSData *data;
1534         if (buffer)
1535             data = buffer->createNSData();
1536         else
1537             data = [[NSData alloc] init];
1538         [d addObject:data];
1539         [data release];
1540         [r addObject:it->second->response().nsURLResponse()];
1541     }
1542
1543     *datas = [d autorelease];
1544     *responses = [r autorelease];
1545 }
1546
1547 - (BOOL)_canProvideDocumentSource
1548 {
1549     String mimeType = _private->coreFrame->loader()->responseMIMEType();
1550     
1551     if (WebCore::DOMImplementation::isTextMIMEType(mimeType) ||
1552         Image::supportsType(mimeType) ||
1553         (_private->coreFrame->page() && _private->coreFrame->page()->pluginData()->supportsMimeType(mimeType)))
1554         return NO;
1555     
1556     return YES;
1557 }
1558
1559 - (BOOL)_canSaveAsWebArchive
1560 {
1561     // Currently, all documents that we can view source for
1562     // (HTML and XML documents) can also be saved as web archives
1563     return [self _canProvideDocumentSource];
1564 }
1565
1566 - (void)_receivedData:(NSData *)data textEncodingName:(NSString *)textEncodingName
1567 {
1568     // Set the encoding. This only needs to be done once, but it's harmless to do it again later.
1569     String encoding;
1570     if (_private->coreFrame)
1571         encoding = _private->coreFrame->loader()->documentLoader()->overrideEncoding();
1572     bool userChosen = !encoding.isNull();
1573     if (encoding.isNull())
1574         encoding = textEncodingName;
1575     _private->coreFrame->loader()->setEncoding(encoding, userChosen);
1576     [self _addData:data];
1577 }
1578
1579 @end
1580
1581 @implementation WebFrame (WebPrivate)
1582
1583 // FIXME: Yhis exists only as a convenience for Safari, consider moving there.
1584 - (BOOL)_isDescendantOfFrame:(WebFrame *)ancestor
1585 {
1586     Frame* coreFrame = core(self);
1587     return coreFrame && coreFrame->tree()->isDescendantOf(core(ancestor));
1588 }
1589
1590 - (void)_setShouldCreateRenderers:(BOOL)shouldCreateRenderers
1591 {
1592     _private->shouldCreateRenderers = shouldCreateRenderers;
1593 }
1594
1595 - (NSColor *)_bodyBackgroundColor
1596 {
1597     Document* document = core(self)->document();
1598     if (!document)
1599         return nil;
1600     HTMLElement* body = document->body();
1601     if (!body)
1602         return nil;
1603     RenderObject* bodyRenderer = body->renderer();
1604     if (!bodyRenderer)
1605         return nil;
1606     Color color = bodyRenderer->style()->backgroundColor();
1607     if (!color.isValid())
1608         return nil;
1609     return nsColor(color);
1610 }
1611
1612 - (BOOL)_isFrameSet
1613 {
1614     return core(self)->isFrameSet();
1615 }
1616
1617 - (BOOL)_firstLayoutDone
1618 {
1619     return [self _frameLoader]->firstLayoutDone();
1620 }
1621
1622 - (WebFrameLoadType)_loadType
1623 {
1624     return (WebFrameLoadType)[self _frameLoader]->loadType();
1625 }
1626
1627 - (NSRange)_selectedNSRange
1628 {
1629     return [self _convertToNSRange:_private->coreFrame->selectionController()->toRange().get()];
1630 }
1631
1632 - (void)_selectNSRange:(NSRange)range
1633 {
1634     RefPtr<Range> domRange = [self _convertToDOMRange:range];
1635     if (domRange)
1636         _private->coreFrame->selectionController()->setSelection(Selection(domRange.get(), SEL_DEFAULT_AFFINITY));
1637 }
1638
1639 - (BOOL)_isDisplayingStandaloneImage
1640 {
1641     Document* document = core(self)->document();
1642     return document && document->isImageDocument();
1643 }
1644
1645 @end
1646
1647 @implementation WebFrame
1648
1649 - (id)init
1650 {
1651     return nil;
1652 }
1653
1654 // Should be deprecated.
1655 - (id)initWithName:(NSString *)name webFrameView:(WebFrameView *)view webView:(WebView *)webView
1656 {
1657     return nil;
1658 }
1659
1660 - (void)dealloc
1661 {
1662     [_private release];
1663     --WebFrameCount;
1664     [super dealloc];
1665 }
1666
1667 - (void)finalize
1668 {
1669     --WebFrameCount;
1670     [super finalize];
1671 }
1672
1673 - (NSString *)name
1674 {
1675     Frame* coreFrame = core(self);
1676     if (!coreFrame)
1677         return nil;
1678     return coreFrame->tree()->name();
1679 }
1680
1681 - (WebFrameView *)frameView
1682 {
1683     return _private->webFrameView;
1684 }
1685
1686 - (WebView *)webView
1687 {
1688     return getWebView(self);
1689 }
1690
1691 - (DOMDocument *)DOMDocument
1692 {
1693     Frame* coreFrame = core(self);
1694     if (!coreFrame)
1695         return nil;
1696     
1697     // FIXME: <rdar://problem/5145841> When loading a custom view/representation 
1698     // into a web frame, the old document can still be around. This makes sure that
1699     // we'll return nil in those cases.
1700     if (![[self _dataSource] _isDocumentHTML]) 
1701         return nil; 
1702
1703     Document* document = coreFrame->document();
1704     
1705     // According to the documentation, we should return nil if the frame doesn't have a document.
1706     // While full-frame images and plugins do have an underlying HTML document, we return nil here to be
1707     // backwards compatible.
1708     if (document && (document->isPluginDocument() || document->isImageDocument()))
1709         return nil;
1710     
1711     return kit(coreFrame->document());
1712 }
1713
1714 - (DOMHTMLElement *)frameElement
1715 {
1716     Frame* coreFrame = core(self);
1717     if (!coreFrame)
1718         return nil;
1719     return kit(coreFrame->ownerElement());
1720 }
1721
1722 - (WebDataSource *)provisionalDataSource
1723 {
1724     FrameLoader* frameLoader = [self _frameLoader];
1725     return frameLoader ? dataSource(frameLoader->provisionalDocumentLoader()) : nil;
1726 }
1727
1728 - (WebDataSource *)dataSource
1729 {
1730     FrameLoader* loader = [self _frameLoader];
1731     if (!loader || !loader->frameHasLoaded())
1732         return nil;
1733
1734     return [self _dataSource];
1735 }
1736
1737 - (void)loadRequest:(NSURLRequest *)request
1738 {
1739     [self _frameLoader]->load(request);
1740 }
1741
1742 static NSURL *createUniqueWebDataURL()
1743 {
1744     CFUUIDRef UUIDRef = CFUUIDCreate(kCFAllocatorDefault);
1745     NSString *UUIDString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, UUIDRef);
1746     CFRelease(UUIDRef);
1747     NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"applewebdata://%@", UUIDString]];
1748     CFRelease(UUIDString);
1749     return URL;
1750 }
1751
1752 - (void)_loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL
1753 {
1754     KURL responseURL;
1755     if (!baseURL) {
1756         baseURL = blankURL();
1757         responseURL = createUniqueWebDataURL();
1758     }
1759     
1760     ResourceRequest request([baseURL absoluteURL]);
1761
1762     // hack because Mail checks for this property to detect data / archive loads
1763     [NSURLProtocol setProperty:@"" forKey:@"WebDataRequest" inRequest:(NSMutableURLRequest *)request.nsURLRequest()];
1764
1765     SubstituteData substituteData(WebCore::SharedBuffer::wrapNSData(data), MIMEType, encodingName, [unreachableURL absoluteURL], responseURL);
1766
1767     [self _frameLoader]->load(request, substituteData);
1768 }
1769
1770
1771 - (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL
1772 {
1773     if (!MIMEType)
1774         MIMEType = @"text/html";
1775     [self _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:baseURL unreachableURL:nil];
1776 }
1777
1778 - (void)_loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL
1779 {
1780     NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
1781     [self _loadData:data MIMEType:@"text/html" textEncodingName:@"UTF-8" baseURL:baseURL unreachableURL:unreachableURL];
1782 }
1783
1784 - (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL
1785 {
1786     [self _loadHTMLString:string baseURL:baseURL unreachableURL:nil];
1787 }
1788
1789 - (void)loadAlternateHTMLString:(NSString *)string baseURL:(NSURL *)baseURL forUnreachableURL:(NSURL *)unreachableURL
1790 {
1791     [self _loadHTMLString:string baseURL:baseURL unreachableURL:unreachableURL];
1792 }
1793
1794 - (void)loadArchive:(WebArchive *)archive
1795 {
1796     WebResource *mainResource = [archive mainResource];
1797     if (mainResource) {
1798         SubstituteData substituteData(WebCore::SharedBuffer::wrapNSData([mainResource data]), [mainResource MIMEType], [mainResource textEncodingName], KURL());
1799         ResourceRequest request([mainResource URL]);
1800
1801         // hack because Mail checks for this property to detect data / archive loads
1802         [NSURLProtocol setProperty:@"" forKey:@"WebDataRequest" inRequest:(NSMutableURLRequest *)request.nsURLRequest()];
1803
1804         RefPtr<DocumentLoader> documentLoader = core(self)->loader()->client()->createDocumentLoader(request, substituteData);
1805
1806         [dataSource(documentLoader.get()) _addToUnarchiveState:archive];
1807
1808         [self _frameLoader]->load(documentLoader.get());
1809     }
1810 }
1811
1812 - (void)stopLoading
1813 {
1814     if (FrameLoader* frameLoader = [self _frameLoader])
1815         frameLoader->stopForUserCancel();
1816 }
1817
1818 - (void)reload
1819 {
1820     [self _frameLoader]->reload();
1821 }
1822
1823 - (WebFrame *)findFrameNamed:(NSString *)name
1824 {
1825     Frame* coreFrame = core(self);
1826     if (!coreFrame)
1827         return nil;
1828     return kit(coreFrame->tree()->find(name));
1829 }
1830
1831 - (WebFrame *)parentFrame
1832 {
1833     Frame* coreFrame = core(self);
1834     if (!coreFrame)
1835         return nil;
1836     return [[kit(coreFrame->tree()->parent()) retain] autorelease];
1837 }
1838
1839 - (NSArray *)childFrames
1840 {
1841     Frame* coreFrame = core(self);
1842     if (!coreFrame)
1843         return [NSArray array];
1844     NSMutableArray *children = [NSMutableArray arrayWithCapacity:coreFrame->tree()->childCount()];
1845     for (Frame* child = coreFrame->tree()->firstChild(); child; child = child->tree()->nextSibling())
1846         [children addObject:kit(child)];
1847     return children;
1848 }
1849
1850 - (WebScriptObject *)windowObject
1851 {
1852     Frame* coreFrame = core(self);
1853     if (!coreFrame)
1854         return 0;
1855     return coreFrame->windowScriptObject();
1856 }
1857
1858 - (JSGlobalContextRef)globalContext
1859 {
1860     Frame* coreFrame = core(self);
1861     if (!coreFrame)
1862         return 0;
1863     return toGlobalRef(coreFrame->scriptProxy()->globalObject()->globalExec());
1864 }
1865
1866 @end