WebCore:
[WebKit-https.git] / WebCore / bridge / mac / WebCoreFrameBridge.mm
1 /*
2  * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.  All rights reserved.
3  * Copyright (C) 2005, 2006 Alexey Proskuryakov (ap@nypop.com)
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #import "config.h"
28 #import "WebCoreFrameBridge.h"
29
30 #import "Cache.h"
31 #import "DOMInternal.h"
32 #import "DOMImplementation.h"
33 #import "DocLoader.h"
34 #import "DocumentFragment.h"
35 #import "DocumentType.h"
36 #import "FrameTree.h"
37 #import "GraphicsContext.h"
38 #import "HTMLFormElement.h"
39 #import "HTMLInputElement.h"
40 #import "AccessibilityObjectCache.h"
41 #import "CharsetNames.h"
42 #import "KWQEditCommand.h"
43 #import "FloatRect.h"
44 #import "FoundationExtras.h"
45 #import "KWQLoader.h"
46 #import "KWQPageState.h"
47 #import "RenderTreeAsText.h"
48 #import "FrameMac.h"
49 #import "Page.h"
50 #import "SelectionController.h"
51 #import "WebCorePageBridge.h"
52 #import "WebCoreSettings.h"
53 #import "WebCoreViewFactory.h"
54 #import "WebCoreWidgetHolder.h"
55 #import "csshelper.h"
56 #import "DeleteSelectionCommand.h"
57 #import "HTMLDocument.h"
58 #import "html_imageimpl.h"
59 #import "htmlediting.h"
60 #import "HTMLNames.h"
61 #import "kjs_proxy.h"
62 #import "kjs_window.h"
63 #import "markup.h"
64 #import "ModifySelectionListLevelCommand.h"
65 #import "MoveSelectionCommand.h"
66 #import "RenderCanvas.h"
67 #import "RenderImage.h"
68 #import "RenderPart.h"
69 #import "ReplaceSelectionCommand.h"
70 #import "RenderWidget.h"
71 #import "TypingCommand.h"
72 #import "TextIterator.h"
73 #import "visible_units.h"
74 #import "xml_tokenizer.h"
75 #import <JavaScriptCore/date_object.h>
76 #import <JavaScriptCore/runtime_root.h>
77
78 @class NSView;
79
80 using namespace std;
81 using namespace WebCore;
82 using namespace HTMLNames;
83
84 using KJS::BooleanType;
85 using KJS::DateInstance;
86 using KJS::ExecState;
87 using KJS::GetterSetterType;
88 using KJS::Identifier;
89 using KJS::Interpreter;
90 using KJS::JSLock;
91 using KJS::JSObject;
92 using KJS::JSType;
93 using KJS::JSValue;
94 using KJS::List;
95 using KJS::NullType;
96 using KJS::NumberType;
97 using KJS::ObjectType;
98 using KJS::SavedBuiltins;
99 using KJS::SavedProperties;
100 using KJS::StringType;
101 using KJS::UString;
102 using KJS::UndefinedType;
103 using KJS::UnspecifiedType;
104 using KJS::Window;
105
106 using KJS::Bindings::RootObject;
107
108 NSString *WebCorePageCacheStateKey = @"WebCorePageCacheState";
109
110 @interface WebCoreFrameBridge (WebCoreBridgeInternal)
111 - (RootObject *)executionContextForView:(NSView *)aView;
112 - (RenderObject::NodeInfo)nodeInfoAtPoint:(NSPoint)point allowShadowContent:(BOOL)allow;
113 @end
114
115 static RootObject *rootForView(void *v)
116 {
117     NSView *aView = (NSView *)v;
118     WebCoreFrameBridge *aBridge = [[WebCoreViewFactory sharedFactory] bridgeForView:aView];
119     RootObject *root = 0;
120
121     if (aBridge)
122         root = [aBridge executionContextForView:aView];
123
124     return root;
125 }
126
127 static pthread_t mainThread = 0;
128
129 static void updateRenderingForBindings (ExecState *exec, JSObject *rootObject)
130 {
131     if (pthread_self() != mainThread)
132         return;
133         
134     if (!rootObject)
135         return;
136         
137     Window *window = static_cast<Window*>(rootObject);
138     if (!window)
139         return;
140         
141     Document *doc = static_cast<Document*>(window->frame()->document());
142     if (doc)
143         doc->updateRendering();
144 }
145
146 static BOOL hasCaseInsensitivePrefix(NSString *string, NSString *prefix)
147 {
148     return [string rangeOfString:prefix options:(NSCaseInsensitiveSearch | NSAnchoredSearch)].location !=
149         NSNotFound;
150 }
151
152 static BOOL isCaseSensitiveEqual(NSString *a, NSString *b)
153 {
154     return [a caseInsensitiveCompare:b] == NSOrderedSame;
155 }
156
157 static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValue* jsValue)
158 {
159     NSAppleEventDescriptor* aeDesc = 0;
160     switch (jsValue->type()) {
161         case BooleanType:
162             aeDesc = [NSAppleEventDescriptor descriptorWithBoolean:jsValue->getBoolean()];
163             break;
164         case StringType:
165             aeDesc = [NSAppleEventDescriptor descriptorWithString:String(jsValue->getString())];
166             break;
167         case NumberType: {
168             Float64 value = jsValue->getNumber();
169             aeDesc = [NSAppleEventDescriptor descriptorWithDescriptorType:typeIEEE64BitFloatingPoint bytes:&value length:sizeof(value)];
170             break;
171         }
172         case ObjectType: {
173             JSObject* object = jsValue->getObject();
174             if (object->inherits(&DateInstance::info)) {
175                 DateInstance* date = static_cast<DateInstance*>(object);
176                 double ms = 0;
177                 int tzOffset = 0;
178                 if (date->getTime(ms, tzOffset)) {
179                     CFAbsoluteTime utcSeconds = ms / 1000 - kCFAbsoluteTimeIntervalSince1970;
180                     LongDateTime ldt;
181                     if (noErr == UCConvertCFAbsoluteTimeToLongDateTime(utcSeconds, &ldt))
182                         aeDesc = [NSAppleEventDescriptor descriptorWithDescriptorType:typeLongDateTime bytes:&ldt length:sizeof(ldt)];
183                 }
184             }
185             if (!aeDesc) {
186                 JSValue* primitive = object->toPrimitive(exec);
187                 if (exec->hadException()) {
188                     exec->clearException();
189                     return [NSAppleEventDescriptor nullDescriptor];
190                 }
191                 return aeDescFromJSValue(exec, primitive);
192             }
193             break;
194         }
195         default:
196             LOG_ERROR("Unknown JavaScript type: %d", jsValue->type());
197             // no break;
198         case UnspecifiedType:
199         case UndefinedType:
200         case NullType:
201         case GetterSetterType:
202             aeDesc = [NSAppleEventDescriptor nullDescriptor];
203             break;
204     }
205     
206     return aeDesc;
207 }
208
209 @implementation WebCoreFrameBridge
210
211 static bool initializedObjectCacheSize = false;
212 static bool initializedKJS = false;
213
214 static inline WebCoreFrameBridge *bridge(Frame *frame)
215 {
216     if (!frame)
217         return nil;
218     return Mac(frame)->bridge();
219 }
220
221 - (WebCoreFrameBridge *)firstChild
222 {
223     return bridge(m_frame->tree()->firstChild());
224 }
225
226 - (WebCoreFrameBridge *)lastChild
227 {
228     return bridge(m_frame->tree()->lastChild());
229 }
230
231 - (unsigned)childCount
232 {
233     return m_frame->tree()->childCount();
234 }
235
236 - (WebCoreFrameBridge *)previousSibling;
237 {
238     return bridge(m_frame->tree()->previousSibling());
239 }
240
241 - (WebCoreFrameBridge *)nextSibling;
242 {
243     return bridge(m_frame->tree()->nextSibling());
244 }
245
246 - (BOOL)isDescendantOfFrame:(WebCoreFrameBridge *)ancestor
247 {
248     return m_frame->tree()->isDescendantOf(ancestor->m_frame);
249 }
250
251 - (WebCoreFrameBridge *)traverseNextFrameStayWithin:(WebCoreFrameBridge *)stayWithin
252 {
253     return bridge(m_frame->tree()->traverseNext(stayWithin->m_frame));
254 }
255
256 - (void)appendChild:(WebCoreFrameBridge *)child
257 {
258     m_frame->tree()->appendChild(adoptRef(child->m_frame));
259 }
260
261 - (void)removeChild:(WebCoreFrameBridge *)child
262 {
263     m_frame->tree()->removeChild(child->m_frame);
264 }
265
266 - (WebCoreFrameBridge *)childFrameNamed:(NSString *)name
267 {
268     return bridge(m_frame->tree()->child(name));
269 }
270
271 - (WebCoreFrameBridge *)nextFrameWithWrap:(BOOL)wrapFlag
272 {
273     return bridge(m_frame->tree()->traverseNextWithWrap(wrapFlag));
274 }
275
276 - (WebCoreFrameBridge *)previousFrameWithWrap:(BOOL)wrapFlag
277 {
278     return bridge(m_frame->tree()->traversePreviousWithWrap(wrapFlag));
279 }
280
281 - (NSString *)domain
282 {
283     Document *doc = m_frame->document();
284     if (doc && doc->isHTMLDocument())
285         return doc->domain();
286     return nil;
287 }
288
289 // FIXME: this is not getting called any more! security regression...
290 - (BOOL)_shouldAllowAccessFrom:(WebCoreFrameBridge *)source
291 {
292     // if no source frame, allow access
293     if (source == nil)
294         return YES;
295
296     //   - allow access if the two frames are in the same window
297     if ([self page] == [source page])
298         return YES;
299
300     //   - allow if the request is made from a local file.
301     NSString *sourceDomain = [self domain];
302     if ([sourceDomain length] == 0)
303         return YES;
304
305     //   - allow access if this frame or one of its ancestors
306     //     has the same origin as source
307     for (WebCoreFrameBridge *ancestor = self; ancestor; ancestor = [ancestor parent]) {
308         NSString *ancestorDomain = [ancestor domain];
309         if (ancestorDomain != nil && 
310             isCaseSensitiveEqual(sourceDomain, ancestorDomain))
311             return YES;
312         
313         ancestor = [ancestor parent];
314     }
315
316     //   - allow access if this frame is a toplevel window and the source
317     //     can access its opener. Note that we only allow one level of
318     //     recursion here.
319     if ([self parent] == nil) {
320         NSString *openerDomain = [[self opener] domain];
321         if (openerDomain != nil && isCaseSensitiveEqual(sourceDomain, openerDomain))
322             return YES;
323     }
324     
325     // otherwise deny access
326     return NO;
327 }
328
329 - (BOOL)canTargetLoadInFrame:(WebCoreFrameBridge *)targetFrame
330 {
331     // This method prevents this exploit:
332     // <rdar://problem/3715785> multiple frame injection vulnerability reported by Secunia, affects almost all browsers
333     
334     // don't mess with navigation within the same page/frameset
335     if ([self page] == [targetFrame page])
336         return YES;
337
338     // Normally, domain should be called on the DOMDocument since it is a DOM method, but this fix is needed for
339     // Jaguar as well where the DOM API doesn't exist.
340     NSString *thisDomain = [self domain];
341     if ([thisDomain length] == 0) {
342         // Allow if the request is made from a local file.
343         return YES;
344     }
345     
346     WebCoreFrameBridge *parentBridge = [targetFrame parent];
347     // Allow if target is an entire window.
348     if (!parentBridge)
349         return YES;
350     
351     NSString *parentDomain = [parentBridge domain];
352     // Allow if the domain of the parent of the targeted frame equals this domain.
353     if (parentDomain && isCaseSensitiveEqual(thisDomain, parentDomain))
354         return YES;
355
356     return NO;
357 }
358
359 - (WebCoreFrameBridge *)findFrameNamed:(NSString *)name
360 {
361     return bridge(m_frame->tree()->find(name));
362 }
363
364 + (NSArray *)supportedMIMETypes
365 {
366     return [NSArray arrayWithObjects:
367         @"text/html",
368         @"text/xml",
369         @"text/xsl",
370         @"text/",
371         @"application/x-javascript",
372         @"application/xml",
373         @"application/xhtml+xml",
374         @"application/rss+xml",
375         @"application/atom+xml",
376         @"application/x-webarchive",
377         @"multipart/x-mixed-replace",
378 #if SVG_SUPPORT
379         @"image/svg+xml",
380 #endif
381         nil];
382 }
383
384 + (WebCoreFrameBridge *)bridgeForDOMDocument:(DOMDocument *)document
385 {
386     return bridge([document _document]->frame());
387 }
388
389 - (id)initMainFrameWithPage:(WebCorePageBridge *)page
390 {
391     if (!initializedKJS) {
392         mainThread = pthread_self();
393         RootObject::setFindRootObjectForNativeHandleFunction(rootForView);
394         KJS::Bindings::Instance::setDidExecuteFunction(updateRenderingForBindings);
395         initializedKJS = true;
396     }
397     
398     if (!(self = [super init]))
399         return nil;
400
401     m_frame = new FrameMac([page impl], 0);
402     m_frame->setBridge(self);
403     _shouldCreateRenderers = YES;
404
405     // FIXME: This is one-time initialization, but it gets the value of the setting from the
406     // current WebView. That's a mismatch and not good!
407     if (!initializedObjectCacheSize) {
408         Cache::setSize([self getObjectCacheSize]);
409         initializedObjectCacheSize = true;
410     }
411     
412     return self;
413 }
414
415 - (id)initSubframeWithRenderer:(RenderPart *)renderer
416 {
417     if (!(self = [super init]))
418         return nil;
419     
420     m_frame = new FrameMac(renderer->node()->document()->frame()->page(), renderer);
421     m_frame->setBridge(self);
422     _shouldCreateRenderers = YES;
423     return self;
424 }
425
426 - (WebCorePageBridge *)page
427 {
428     return m_frame->page()->bridge();
429 }
430
431 - (void)initializeSettings:(WebCoreSettings *)settings
432 {
433     m_frame->setSettings([settings settings]);
434 }
435
436 - (void)dealloc
437 {
438     [self removeFromFrame];
439     [super dealloc];
440 }
441
442 - (void)finalize
443 {
444     // FIXME: This work really should not be done at deallocation time.
445     // We need to do it at some well-defined time instead.
446     [self removeFromFrame];
447     [super finalize];
448 }
449
450 - (WebCoreFrameBridge *)parent
451 {
452     return bridge(m_frame->tree()->parent());
453 }
454
455 - (void)provisionalLoadStarted
456 {
457     m_frame->provisionalLoadStarted();
458 }
459
460 - (void)openURL:(NSURL *)URL reload:(BOOL)reload contentType:(NSString *)contentType refresh:(NSString *)refresh lastModified:(NSDate *)lastModified pageCache:(NSDictionary *)pageCache
461 {
462     if (pageCache) {
463         KWQPageState *state = [pageCache objectForKey:WebCorePageCacheStateKey];
464         m_frame->openURLFromPageCache(state);
465         [state invalidate];
466         return;
467     }
468         
469     // arguments
470     ResourceRequest request(m_frame->resourceRequest());
471     request.reload = reload;
472     if (contentType)
473         request.m_responseMIMEType = contentType;
474     m_frame->setResourceRequest(request);
475
476     // opening the URL
477     if (m_frame->didOpenURL(URL)) {
478         // things we have to set up after calling didOpenURL
479         if (refresh) {
480             m_frame->addMetaData("http-refresh", refresh);
481         }
482         if (lastModified) {
483             NSString *modifiedString = [lastModified descriptionWithCalendarFormat:@"%a %b %d %Y %H:%M:%S" timeZone:nil locale:nil];
484             m_frame->addMetaData("modified", modifiedString);
485         }
486     }
487 }
488
489 - (void)setEncoding:(NSString *)encoding userChosen:(BOOL)userChosen
490 {
491     m_frame->setEncoding(DeprecatedString::fromNSString(encoding), userChosen);
492 }
493
494 - (void)addData:(NSData *)data
495 {
496     Document *doc = m_frame->document();
497     
498     // Document may be nil if the part is about to redirect
499     // as a result of JS executing during load, i.e. one frame
500     // changing another's location before the frame's document
501     // has been created. 
502     if (doc) {
503         doc->setShouldCreateRenderers([self shouldCreateRenderers]);
504         m_frame->addData((const char *)[data bytes], [data length]);
505     }
506 }
507
508 - (void)closeURL
509 {
510     m_frame->closeURL();
511 }
512
513 - (void)stopLoading
514 {
515     m_frame->stopLoading();
516 }
517
518 - (void)didNotOpenURL:(NSURL *)URL pageCache:(NSDictionary *)pageCache
519 {
520     m_frame->didNotOpenURL(KURL(URL).url());
521
522     // We might have made a page cache item, but now we're bailing out due to an error before we ever
523     // transitioned to the new page (before WebFrameState==commit).  The goal here is to restore any state
524     // so that the existing view (that wenever got far enough to replace) can continue being used.
525     Document *doc = m_frame->document();
526     if (doc)
527         doc->setInPageCache(NO);
528
529     KWQPageState *state = [pageCache objectForKey:WebCorePageCacheStateKey];
530
531     // FIXME: This is a grotesque hack to fix <rdar://problem/4059059> Crash in RenderFlow::detach
532     // Somehow the KWQPageState object is not properly updated, and is holding onto a stale document
533     // both Xcode and FileMaker see this crash, Safari does not.
534     // This if check MUST be removed as part of re-writing the loader down in WebCore
535     ASSERT(!state || ([state document] == doc));
536     if ([state document] == doc)
537         [state invalidate];
538 }
539
540 - (BOOL)canLoadURL:(NSURL *)URL fromReferrer:(NSString *)referrer hideReferrer:(BOOL *)hideReferrer
541 {
542     BOOL referrerIsWebURL = hasCaseInsensitivePrefix(referrer, @"http:") || hasCaseInsensitivePrefix(referrer, @"https:");
543     BOOL referrerIsLocalURL = hasCaseInsensitivePrefix(referrer, @"file:") || hasCaseInsensitivePrefix(referrer, @"applewebdata:");
544     BOOL URLIsFileURL = [URL scheme] != NULL && [[URL scheme] compare:@"file" options:(NSCaseInsensitiveSearch|NSLiteralSearch)] == NSOrderedSame;
545     BOOL referrerIsSecureURL = hasCaseInsensitivePrefix(referrer, @"https:");
546     BOOL URLIsSecureURL = [URL scheme] != NULL && [[URL scheme] compare:@"https" options:(NSCaseInsensitiveSearch|NSLiteralSearch)] == NSOrderedSame;
547
548     
549     *hideReferrer = !referrerIsWebURL || (referrerIsSecureURL && !URLIsSecureURL);
550     return !URLIsFileURL || referrerIsLocalURL;
551 }
552
553 - (void)saveDocumentState
554 {
555     Vector<String> stateVector;
556     if (Document* doc = m_frame->document())
557         stateVector = doc->formElementsState();
558     size_t size = stateVector.size();
559     NSMutableArray* stateArray = [[NSMutableArray alloc] initWithCapacity:size];
560     for (size_t i = 0; i < size; ++i) {
561         NSString* s = stateVector[i];
562         id o = s ? (id)s : (id)[NSNull null];
563         [stateArray addObject:o];
564     }
565     [self saveDocumentState:stateArray];
566     [stateArray release];
567 }
568
569 - (void)restoreDocumentState
570 {
571     Document* doc = m_frame->document();
572     if (!doc)
573         return;
574     NSArray* stateArray = [self documentState];
575     size_t size = [stateArray count];
576     Vector<String> stateVector;
577     stateVector.reserveCapacity(size);
578     for (size_t i = 0; i < size; ++i) {
579         id o = [stateArray objectAtIndex:i];
580         NSString* s = [o isKindOfClass:[NSString class]] ? o : 0;
581         stateVector.append(s);
582     }
583     doc->setStateForNewFormElements(stateVector);
584 }
585
586 - (void)scrollToAnchorWithURL:(NSURL *)URL
587 {
588     m_frame->scrollToAnchor(KURL(URL).url().latin1());
589 }
590
591 - (BOOL)scrollOverflowInDirection:(WebScrollDirection)direction granularity:(WebScrollGranularity)granularity
592 {
593     if (!m_frame)
594         return NO;
595     return m_frame->scrollOverflow((KWQScrollDirection)direction, (KWQScrollGranularity)granularity);
596 }
597
598 - (BOOL)sendScrollWheelEvent:(NSEvent *)event
599 {
600     return m_frame ? m_frame->wheelEvent(event) : NO;
601 }
602
603 - (BOOL)saveDocumentToPageCache
604 {
605     Document *doc = m_frame->document();
606     if (!doc)
607         return NO;
608     if (!doc->view())
609         return NO;
610
611     m_frame->clearTimers();
612
613     JSLock lock;
614
615     SavedProperties *windowProperties = new SavedProperties;
616     m_frame->saveWindowProperties(windowProperties);
617
618     SavedProperties *locationProperties = new SavedProperties;
619     m_frame->saveLocationProperties(locationProperties);
620     
621     SavedBuiltins *interpreterBuiltins = new SavedBuiltins;
622     m_frame->saveInterpreterBuiltins(*interpreterBuiltins);
623
624     KWQPageState *pageState = [[KWQPageState alloc] initWithDocument:doc
625                                                                  URL:m_frame->url()
626                                                     windowProperties:windowProperties
627                                                   locationProperties:locationProperties
628                                                  interpreterBuiltins:interpreterBuiltins
629                                                       pausedTimeouts:m_frame->pauseTimeouts()];
630
631     BOOL result = [self saveDocumentToPageCache:pageState];
632
633     [pageState release];
634
635     return result;
636 }
637
638 - (BOOL)canCachePage
639 {
640     return m_frame->canCachePage();
641 }
642
643 - (void)clear
644 {
645     m_frame->clear();
646 }
647
648 - (void)end
649 {
650     m_frame->end();
651 }
652
653 - (void)stop
654 {
655     m_frame->stop();
656 }
657
658 - (void)clearFrame
659 {
660     m_frame = 0;
661 }
662
663 - (void)handleFallbackContent
664 {
665     // this needs to be callable even after teardown of the frame
666     if (!m_frame)
667         return;
668     m_frame->handleFallbackContent();
669 }
670
671 - (void)createFrameViewWithNSView:(NSView *)view marginWidth:(int)mw marginHeight:(int)mh
672 {
673     // If we own the view, delete the old one - otherwise the render m_frame will take care of deleting the view.
674     [self removeFromFrame];
675
676     FrameView* frameView = new FrameView(m_frame);
677     m_frame->setView(frameView);
678     frameView->deref();
679
680     frameView->setView(view);
681     if (mw >= 0)
682         frameView->setMarginWidth(mw);
683     if (mh >= 0)
684         frameView->setMarginHeight(mh);
685 }
686
687 - (void)scrollToAnchor:(NSString *)anchor
688 {
689     m_frame->gotoAnchor(anchor);
690 }
691
692 - (BOOL)isSelectionEditable
693 {
694     return m_frame->selection().isContentEditable();
695 }
696
697 - (BOOL)isSelectionRichlyEditable
698 {
699     return m_frame->selection().isContentRichlyEditable();
700 }
701
702 - (WebSelectionState)selectionState
703 {
704     switch (m_frame->selection().state()) {
705         case WebCore::Selection::NONE:
706             return WebSelectionStateNone;
707         case WebCore::Selection::CARET:
708             return WebSelectionStateCaret;
709         case WebCore::Selection::RANGE:
710             return WebSelectionStateRange;
711     }
712     
713     ASSERT_NOT_REACHED();
714     return WebSelectionStateNone;
715 }
716
717 - (NSString *)_stringWithDocumentTypeStringAndMarkupString:(NSString *)markupString
718 {
719     return m_frame->documentTypeString() + markupString;
720 }
721
722 - (NSArray *)nodesFromList:(DeprecatedPtrList<Node> *)nodeList
723 {
724     NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:nodeList->count()];
725     for (DeprecatedPtrListIterator<Node> i(*nodeList); i.current(); ++i)
726         [nodes addObject:[DOMNode _nodeWith:i.current()]];
727
728     return nodes;
729 }
730
731 - (NSString *)markupStringFromNode:(DOMNode *)node nodes:(NSArray **)nodes
732 {
733     // FIXME: This is never "for interchange". Is that right? See the next method.
734     DeprecatedPtrList<Node> nodeList;
735     NSString *markupString = createMarkup([node _node], IncludeNode, nodes ? &nodeList : 0).getNSString();
736     if (nodes)
737         *nodes = [self nodesFromList:&nodeList];
738
739     return [self _stringWithDocumentTypeStringAndMarkupString:markupString];
740 }
741
742 - (NSString *)markupStringFromRange:(DOMRange *)range nodes:(NSArray **)nodes
743 {
744     // FIXME: This is always "for interchange". Is that right? See the previous method.
745     DeprecatedPtrList<Node> nodeList;
746     NSString *markupString = createMarkup([range _range], nodes ? &nodeList : 0, AnnotateForInterchange).getNSString();
747     if (nodes)
748         *nodes = [self nodesFromList:&nodeList];
749
750     return [self _stringWithDocumentTypeStringAndMarkupString:markupString];
751 }
752
753 - (NSString *)selectedString
754 {
755     String text = m_frame->selectedText();
756     text.replace('\\', m_frame->backslashAsCurrencySymbol());
757     return [[(NSString*)text copy] autorelease];
758 }
759
760 - (NSString *)stringForRange:(DOMRange *)range
761 {
762     String text = plainText([range _range]);
763     text.replace('\\', m_frame->backslashAsCurrencySymbol());
764     return [[(NSString*)text copy] autorelease];
765 }
766
767 - (void)selectAll
768 {
769     m_frame->selectAll();
770 }
771
772 - (void)deselectAll
773 {
774     [self deselectText];
775     Document *doc = m_frame->document();
776     if (doc) {
777         doc->setFocusNode(0);
778     }
779 }
780
781 - (void)deselectText
782 {
783     // FIXME: 6498 Should just be able to call m_frame->selection().clear()
784     m_frame->setSelection(SelectionController());
785 }
786
787 - (BOOL)isFrameSet
788 {
789     return m_frame->isFrameSet();
790 }
791
792 - (void)reapplyStylesForDeviceType:(WebCoreDeviceType)deviceType
793 {
794     m_frame->setMediaType(deviceType == WebCoreDeviceScreen ? "screen" : "print");
795     Document *doc = m_frame->document();
796     if (doc)
797         doc->setPrinting(deviceType == WebCoreDevicePrinter);
798     return m_frame->reparseConfiguration();
799 }
800
801 static BOOL nowPrinting(WebCoreFrameBridge *self)
802 {
803     Document *doc = self->m_frame->document();
804     return doc && doc->printing();
805 }
806
807 // Set or unset the printing mode in the view.  We only toy with this if we're printing.
808 - (void)_setupRootForPrinting:(BOOL)onOrOff
809 {
810     if (nowPrinting(self)) {
811         RenderCanvas *root = static_cast<RenderCanvas *>(m_frame->document()->renderer());
812         if (root) {
813             root->setPrintingMode(onOrOff);
814         }
815     }
816 }
817
818 - (void)forceLayoutAdjustingViewSize:(BOOL)flag
819 {
820     [self _setupRootForPrinting:YES];
821     m_frame->forceLayout();
822     if (flag) {
823         [self adjustViewSize];
824     }
825     [self _setupRootForPrinting:NO];
826 }
827
828 - (void)forceLayoutWithMinimumPageWidth:(float)minPageWidth maximumPageWidth:(float)maxPageWidth adjustingViewSize:(BOOL)flag
829 {
830     [self _setupRootForPrinting:YES];
831     m_frame->forceLayoutWithPageWidthRange(minPageWidth, maxPageWidth);
832     if (flag) {
833         [self adjustViewSize];
834     }
835     [self _setupRootForPrinting:NO];
836 }
837
838 - (void)sendResizeEvent
839 {
840     m_frame->sendResizeEvent();
841 }
842
843 - (void)sendScrollEvent
844 {
845     m_frame->sendScrollEvent();
846 }
847
848 - (void)drawRect:(NSRect)rect
849 {
850     PlatformGraphicsContext* platformContext = static_cast<PlatformGraphicsContext*>([[NSGraphicsContext currentContext] graphicsPort]);
851     ASSERT([[NSGraphicsContext currentContext] isFlipped]);
852     ASSERT(!m_frame->document() || m_frame->document()->printing() == ![NSGraphicsContext currentContextDrawingToScreen]);
853     GraphicsContext context(platformContext);
854     context.setUsesInactiveTextBackgroundColor(!m_frame->displaysWithFocusAttributes());
855     [self _setupRootForPrinting:YES];
856     m_frame->paint(&context, enclosingIntRect(rect));
857     [self _setupRootForPrinting:NO];
858 }
859
860 // Used by pagination code called from AppKit when a standalone web page is printed.
861 - (NSArray*)computePageRectsWithPrintWidthScaleFactor:(float)printWidthScaleFactor printHeight:(float)printHeight
862 {
863     [self _setupRootForPrinting:YES];
864     NSMutableArray* pages = [NSMutableArray arrayWithCapacity:5];
865     if (printWidthScaleFactor <= 0) {
866         LOG_ERROR("printWidthScaleFactor has bad value %.2f", printWidthScaleFactor);
867         return pages;
868     }
869     
870     if (printHeight <= 0) {
871         LOG_ERROR("printHeight has bad value %.2f", printHeight);
872         return pages;
873     }
874
875     if (!m_frame || !m_frame->document() || !m_frame->view()) return pages;
876     RenderCanvas* root = static_cast<RenderCanvas *>(m_frame->document()->renderer());
877     if (!root) return pages;
878     
879     FrameView* view = m_frame->view();
880     NSView* documentView = view->getDocumentView();
881     if (!documentView)
882         return pages;
883
884     float currPageHeight = printHeight;
885     float docHeight = root->layer()->height();
886     float docWidth = root->layer()->width();
887     float printWidth = docWidth/printWidthScaleFactor;
888     
889     // We need to give the part the opportunity to adjust the page height at each step.
890     for (float i = 0; i < docHeight; i += currPageHeight) {
891         float proposedBottom = min(docHeight, i + printHeight);
892         m_frame->adjustPageHeight(&proposedBottom, i, proposedBottom, i);
893         currPageHeight = max(1.0f, proposedBottom - i);
894         for (float j = 0; j < docWidth; j += printWidth) {
895             NSValue* val = [NSValue valueWithRect: NSMakeRect(j, i, printWidth, currPageHeight)];
896             [pages addObject: val];
897         }
898     }
899     [self _setupRootForPrinting:NO];
900     
901     return pages;
902 }
903
904 // This is to support the case where a webview is embedded in the view that's being printed
905 - (void)adjustPageHeightNew:(float *)newBottom top:(float)oldTop bottom:(float)oldBottom limit:(float)bottomLimit
906 {
907     [self _setupRootForPrinting:YES];
908     m_frame->adjustPageHeight(newBottom, oldTop, oldBottom, bottomLimit);
909     [self _setupRootForPrinting:NO];
910 }
911
912 - (NSObject *)copyRenderNode:(RenderObject *)node copier:(id <WebCoreRenderTreeCopier>)copier
913 {
914     NSMutableArray *children = [[NSMutableArray alloc] init];
915     for (RenderObject *child = node->firstChild(); child; child = child->nextSibling()) {
916         [children addObject:[self copyRenderNode:child copier:copier]];
917     }
918           
919     NSString *name = [[NSString alloc] initWithUTF8String:node->renderName()];
920     
921     RenderWidget* renderWidget = node->isWidget() ? static_cast<RenderWidget*>(node) : 0;
922     Widget* widget = renderWidget ? renderWidget->widget() : 0;
923     NSView *view = widget ? widget->getView() : nil;
924     
925     int nx, ny;
926     node->absolutePosition(nx, ny);
927     NSObject *copiedNode = [copier nodeWithName:name
928                                        position:NSMakePoint(nx,ny)
929                                            rect:NSMakeRect(node->xPos(), node->yPos(), node->width(), node->height())
930                                            view:view
931                                        children:children];
932     
933     [name release];
934     [children release];
935     
936     return copiedNode;
937 }
938
939 - (NSObject *)copyRenderTree:(id <WebCoreRenderTreeCopier>)copier
940 {
941     RenderObject *renderer = m_frame->renderer();
942     if (!renderer) {
943         return nil;
944     }
945     return [self copyRenderNode:renderer copier:copier];
946 }
947
948 - (void)removeFromFrame
949 {
950     if (m_frame)
951         m_frame->setView(0);
952 }
953
954 - (void)installInFrame:(NSView *)view
955 {
956     // If this isn't the main frame, it must have a render m_frame set, or it
957     // won't ever get installed in the view hierarchy.
958     ASSERT(self == [[self page] mainFrame] || m_frame->ownerRenderer());
959
960     m_frame->view()->setView(view);
961     // FIXME: frame tries to do this too, is it needed?
962     if (m_frame->ownerRenderer()) {
963         m_frame->ownerRenderer()->setWidget(m_frame->view());
964         // Now the render part owns the view, so we don't any more.
965     }
966
967     m_frame->view()->initScrollBars();
968 }
969
970 - (void)setActivationEventNumber:(int)num
971 {
972     m_frame->setActivationEventNumber(num);
973 }
974
975 - (void)mouseDown:(NSEvent *)event
976 {
977     m_frame->mouseDown(event);
978 }
979
980 - (void)mouseDragged:(NSEvent *)event
981 {
982     m_frame->mouseDragged(event);
983 }
984
985 - (void)mouseUp:(NSEvent *)event
986 {
987     m_frame->mouseUp(event);
988 }
989
990 - (void)mouseMoved:(NSEvent *)event
991 {
992     m_frame->mouseMoved(event);
993 }
994
995 - (BOOL)sendContextMenuEvent:(NSEvent *)event
996 {
997     return m_frame->sendContextMenuEvent(event);
998 }
999
1000 - (DOMElement*)elementForView:(NSView*)view
1001 {
1002     // FIXME: implemented currently for only a subset of the KWQ widgets
1003     if ([view conformsToProtocol:@protocol(WebCoreWidgetHolder)]) {
1004         NSView <WebCoreWidgetHolder>* widgetHolder = view;
1005         Widget* widget = [widgetHolder widget];
1006         if (widget && widget->client())
1007             return [DOMElement _elementWith:widget->client()->element(widget)];
1008     }
1009     return nil;
1010 }
1011
1012 static HTMLInputElement* inputElementFromDOMElement(DOMElement* element)
1013 {
1014     Node* node = [element _node];
1015     if (node->hasTagName(inputTag))
1016         return static_cast<HTMLInputElement*>(node);
1017     return nil;
1018 }
1019
1020 static HTMLFormElement *formElementFromDOMElement(DOMElement *element)
1021 {
1022     Node *node = [element _node];
1023     // This should not be necessary, but an XSL file on
1024     // maps.google.com crashes otherwise because it is an xslt file
1025     // that contains <form> elements that aren't in any namespace, so
1026     // they come out as generic CML elements
1027     if (node && node->hasTagName(formTag)) {
1028         return static_cast<HTMLFormElement *>(node);
1029     }
1030     return nil;
1031 }
1032
1033 - (DOMElement *)elementWithName:(NSString *)name inForm:(DOMElement *)form
1034 {
1035     HTMLFormElement *formElement = formElementFromDOMElement(form);
1036     if (formElement) {
1037         Vector<HTMLGenericFormElement*>& elements = formElement->formElements;
1038         AtomicString targetName = name;
1039         for (unsigned int i = 0; i < elements.size(); i++) {
1040             HTMLGenericFormElement *elt = elements[i];
1041             // Skip option elements, other duds
1042             if (elt->name() == targetName)
1043                 return [DOMElement _elementWith:elt];
1044         }
1045     }
1046     return nil;
1047 }
1048
1049 - (BOOL)elementDoesAutoComplete:(DOMElement *)element
1050 {
1051     HTMLInputElement *inputElement = inputElementFromDOMElement(element);
1052     return inputElement != nil
1053         && inputElement->inputType() == HTMLInputElement::TEXT
1054         && inputElement->autoComplete();
1055 }
1056
1057 - (BOOL)elementIsPassword:(DOMElement *)element
1058 {
1059     HTMLInputElement *inputElement = inputElementFromDOMElement(element);
1060     return inputElement != nil
1061         && inputElement->inputType() == HTMLInputElement::PASSWORD;
1062 }
1063
1064 - (DOMElement *)formForElement:(DOMElement *)element;
1065 {
1066     HTMLInputElement *inputElement = inputElementFromDOMElement(element);
1067     if (inputElement) {
1068         HTMLFormElement *formElement = inputElement->form();
1069         if (formElement) {
1070             return [DOMElement _elementWith:formElement];
1071         }
1072     }
1073     return nil;
1074 }
1075
1076 - (DOMElement *)currentForm
1077 {
1078     return [DOMElement _elementWith:m_frame->currentForm()];
1079 }
1080
1081 - (NSArray *)controlsInForm:(DOMElement *)form
1082 {
1083     NSMutableArray *results = nil;
1084     HTMLFormElement *formElement = formElementFromDOMElement(form);
1085     if (formElement) {
1086         Vector<HTMLGenericFormElement*>& elements = formElement->formElements;
1087         for (unsigned int i = 0; i < elements.size(); i++) {
1088             if (elements.at(i)->isEnumeratable()) { // Skip option elements, other duds
1089                 DOMElement *de = [DOMElement _elementWith:elements.at(i)];
1090                 if (!results) {
1091                     results = [NSMutableArray arrayWithObject:de];
1092                 } else {
1093                     [results addObject:de];
1094                 }
1095             }
1096         }
1097     }
1098     return results;
1099 }
1100
1101 - (NSString *)searchForLabels:(NSArray *)labels beforeElement:(DOMElement *)element
1102 {
1103     return m_frame->searchForLabelsBeforeElement(labels, [element _element]);
1104 }
1105
1106 - (NSString *)matchLabels:(NSArray *)labels againstElement:(DOMElement *)element
1107 {
1108     return m_frame->matchLabelsAgainstElement(labels, [element _element]);
1109 }
1110
1111 - (void)getInnerNonSharedNode:(DOMNode **)innerNonSharedNode innerNode:(DOMNode **)innerNode URLElement:(DOMElement **)URLElement atPoint:(NSPoint)point allowShadowContent:(BOOL) allow
1112 {
1113     RenderObject *renderer = m_frame->renderer();
1114     if (!renderer) {
1115         *innerNonSharedNode = nil;
1116         *innerNode = nil;
1117         *URLElement = nil;
1118         return;
1119     }
1120
1121     RenderObject::NodeInfo nodeInfo = [self nodeInfoAtPoint:point allowShadowContent:allow];
1122     *innerNonSharedNode = [DOMNode _nodeWith:nodeInfo.innerNonSharedNode()];
1123     *innerNode = [DOMNode _nodeWith:nodeInfo.innerNode()];
1124     *URLElement = [DOMElement _elementWith:nodeInfo.URLElement()];
1125 }
1126
1127 - (BOOL)isPointInsideSelection:(NSPoint)point
1128 {
1129     return m_frame->isPointInsideSelection(IntPoint(point));
1130 }
1131
1132 - (NSURL *)URLWithAttributeString:(NSString *)string
1133 {
1134     Document *doc = m_frame->document();
1135     if (!doc)
1136         return nil;
1137     // FIXME: is parseURL appropriate here?
1138     DeprecatedString rel = parseURL(string).deprecatedString();
1139     return KURL(doc->completeURL(rel)).getNSURL();
1140 }
1141
1142 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag
1143 {
1144     return m_frame->findString(string, forward, caseFlag, wrapFlag);
1145 }
1146
1147 - (unsigned)highlightAllMatchesForString:(NSString *)string caseSensitive:(BOOL)caseFlag
1148 {
1149     return m_frame->highlightAllMatchesForString(string, caseFlag);
1150 }
1151
1152 - (void)clearHighlightedMatches
1153 {
1154     Document *doc = m_frame->document();
1155     if (!doc) {
1156         return;
1157     }
1158     doc->removeMarkers(DocumentMarker::TextMatch);
1159 }
1160
1161 - (NSString *)advanceToNextMisspelling
1162 {
1163     return m_frame->advanceToNextMisspelling();
1164 }
1165
1166 - (NSString *)advanceToNextMisspellingStartingJustBeforeSelection
1167 {
1168     return m_frame->advanceToNextMisspelling(true);
1169 }
1170
1171 - (void)unmarkAllMisspellings
1172 {
1173     Document *doc = m_frame->document();
1174     if (!doc) {
1175         return;
1176     }
1177     doc->removeMarkers(DocumentMarker::Spelling);
1178 }
1179
1180 - (void)setTextSizeMultiplier:(float)multiplier
1181 {
1182     int newZoomFactor = (int)rint(multiplier * 100);
1183     if (m_frame->zoomFactor() == newZoomFactor) {
1184         return;
1185     }
1186     m_frame->setZoomFactor(newZoomFactor);
1187 }
1188
1189 - (CFStringEncoding)textEncoding
1190 {
1191     return WebCore::TextEncoding(m_frame->encoding().latin1()).encodingID();
1192 }
1193
1194 - (NSView *)nextKeyView
1195 {
1196     Document *doc = m_frame->document();
1197     if (!doc)
1198         return nil;
1199     return m_frame->nextKeyView(doc->focusNode(), KWQSelectingNext);
1200 }
1201
1202 - (NSView *)previousKeyView
1203 {
1204     Document *doc = m_frame->document();
1205     if (!doc)
1206         return nil;
1207     return m_frame->nextKeyView(doc->focusNode(), KWQSelectingPrevious);
1208 }
1209
1210 - (NSView *)nextKeyViewInsideWebFrameViews
1211 {
1212     Document *doc = m_frame->document();
1213     if (!doc)
1214         return nil;
1215     return m_frame->nextKeyViewInFrameHierarchy(doc->focusNode(), KWQSelectingNext);
1216 }
1217
1218 - (NSView *)previousKeyViewInsideWebFrameViews
1219 {
1220     Document *doc = m_frame->document();
1221     if (!doc)
1222         return nil;
1223     return m_frame->nextKeyViewInFrameHierarchy(doc->focusNode(), KWQSelectingPrevious);
1224 }
1225
1226 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)string
1227 {
1228     return [self stringByEvaluatingJavaScriptFromString:string forceUserGesture:true];
1229 }
1230
1231 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)string forceUserGesture:(BOOL)forceUserGesture
1232 {
1233     m_frame->createEmptyDocument();
1234     JSValue* result = m_frame->executeScript(0, DeprecatedString::fromNSString(string), forceUserGesture);
1235     if (!result || !result->isString())
1236         return 0;
1237     JSLock lock;
1238     return String(result->getString());
1239 }
1240
1241 - (NSAppleEventDescriptor *)aeDescByEvaluatingJavaScriptFromString:(NSString *)string
1242 {
1243     m_frame->createEmptyDocument();
1244     JSValue* result = m_frame->executeScript(0, DeprecatedString::fromNSString(string), true);
1245     if (!result) // FIXME: pass errors
1246         return 0;
1247     JSLock lock;
1248     return aeDescFromJSValue(m_frame->jScript()->interpreter()->globalExec(), result);
1249 }
1250
1251 - (WebScriptObject *)windowScriptObject
1252 {
1253     return m_frame->windowScriptObject();
1254 }
1255
1256 - (NPObject *)windowScriptNPObject
1257 {
1258     return m_frame->windowScriptNPObject();
1259 }
1260
1261 - (DOMDocument *)DOMDocument
1262 {
1263     return [DOMDocument _documentWith:m_frame->document()];
1264 }
1265
1266 - (DOMHTMLElement *)frameElement
1267 {
1268     // Not [[self DOMDocument] _ownerElement], since our doc is not set up at the start of our own load.
1269     // FIXME: There really is no guarantee this is an HTML element.
1270     // For example, it could be something like an SVG foreign object element.
1271     // Because of that, I believe the cast here is wrong and also the public API
1272     // of WebKit might have to be changed.
1273     return (DOMHTMLElement *)[DOMElement _elementWith:m_frame->ownerElement()];
1274 }
1275
1276 - (NSAttributedString *)selectedAttributedString
1277 {
1278     // FIXME: should be a no-arg version of attributedString() that does this
1279     return m_frame->attributedString(m_frame->selection().start().node(), m_frame->selection().start().offset(), m_frame->selection().end().node(), m_frame->selection().end().offset());
1280 }
1281
1282 - (NSAttributedString *)attributedStringFrom:(DOMNode *)start startOffset:(int)startOffset to:(DOMNode *)end endOffset:(int)endOffset
1283 {
1284     return m_frame->attributedString([start _node], startOffset, [end _node], endOffset);
1285 }
1286
1287 - (NSRect)selectionRect
1288 {
1289     return m_frame->selectionRect(); 
1290 }
1291
1292 - (NSRect)visibleSelectionRect
1293 {
1294     return m_frame->visibleSelectionRect(); 
1295 }
1296
1297 - (void)centerSelectionInVisibleArea
1298 {
1299     m_frame->centerSelectionInVisibleArea(); 
1300 }
1301
1302 - (NSRect)caretRectAtNode:(DOMNode *)node offset:(int)offset affinity:(NSSelectionAffinity)affinity
1303 {
1304     return [node _node]->renderer()->caretRect(offset, static_cast<EAffinity>(affinity));
1305 }
1306 - (NSRect)firstRectForDOMRange:(DOMRange *)range
1307 {
1308     int extraWidthToEndOfLine = 0;
1309     IntRect startCaretRect = [[range startContainer] _node]->renderer()->caretRect([range startOffset], DOWNSTREAM, &extraWidthToEndOfLine);
1310     IntRect endCaretRect = [[range endContainer] _node]->renderer()->caretRect([range endOffset], UPSTREAM);
1311
1312     if (startCaretRect.y() == endCaretRect.y()) {
1313         // start and end are on the same line
1314         return IntRect(MIN(startCaretRect.x(), endCaretRect.x()), 
1315                      startCaretRect.y(), 
1316                      abs(endCaretRect.x() - startCaretRect.x()),
1317                      MAX(startCaretRect.height(), endCaretRect.height()));
1318     }
1319
1320     // start and end aren't on the same line, so go from start to the end of its line
1321     return IntRect(startCaretRect.x(), 
1322                  startCaretRect.y(),
1323                  startCaretRect.width() + extraWidthToEndOfLine,
1324                  startCaretRect.height());
1325 }
1326
1327 - (NSImage *)selectionImage
1328 {
1329     return m_frame->selectionImage();
1330 }
1331
1332 - (void)setName:(NSString *)name
1333 {
1334     m_frame->tree()->setName(name);
1335 }
1336
1337 - (NSString *)name
1338 {
1339     return m_frame->tree()->name();
1340 }
1341
1342 - (NSURL *)URL
1343 {
1344     return m_frame->url().getNSURL();
1345 }
1346
1347 - (NSURL *)baseURL
1348 {
1349     return m_frame->completeURL(m_frame->document()->baseURL()).getNSURL();
1350 }
1351
1352 - (NSString *)referrer
1353 {
1354     return m_frame->referrer().getNSString();
1355 }
1356
1357 - (WebCoreFrameBridge *)opener
1358 {
1359     Frame *openerPart = m_frame->opener();
1360
1361     if (openerPart)
1362         return Mac(openerPart)->bridge();
1363
1364     return nil;
1365 }
1366
1367 - (void)setOpener:(WebCoreFrameBridge *)bridge;
1368 {
1369     Frame *p = [bridge impl];
1370     
1371     if (p)
1372         p->setOpener(m_frame);
1373 }
1374
1375 + (NSString *)stringWithData:(NSData *)data textEncoding:(CFStringEncoding)textEncoding
1376 {
1377     if (textEncoding == kCFStringEncodingInvalidId)
1378         textEncoding = kCFStringEncodingWindowsLatin1;
1379
1380     return WebCore::TextEncoding(textEncoding).toUnicode((const char*)[data bytes], [data length]).getNSString();
1381 }
1382
1383 + (NSString *)stringWithData:(NSData *)data textEncodingName:(NSString *)textEncodingName
1384 {
1385     CFStringEncoding textEncoding = WebCore::TextEncoding([textEncodingName lossyCString]).encodingID();
1386     return [WebCoreFrameBridge stringWithData:data textEncoding:textEncoding];
1387 }
1388
1389 - (BOOL)needsLayout
1390 {
1391     RenderObject *renderer = m_frame->renderer();
1392     return renderer ? renderer->needsLayout() : false;
1393 }
1394
1395 - (void)setNeedsLayout
1396 {
1397     RenderObject *renderer = m_frame->renderer();
1398     if (renderer)
1399         renderer->setNeedsLayout(true);
1400 }
1401
1402 - (BOOL)interceptKeyEvent:(NSEvent *)event toView:(NSView *)view
1403 {
1404     return m_frame->keyEvent(event);
1405 }
1406
1407 - (NSString *)renderTreeAsExternalRepresentation
1408 {
1409     return externalRepresentation(m_frame->renderer()).getNSString();
1410 }
1411
1412 - (void)setSelectionFromNone
1413 {
1414     m_frame->setSelectionFromNone();
1415 }
1416
1417 - (void)setDisplaysWithFocusAttributes:(BOOL)flag
1418 {
1419     m_frame->setDisplaysWithFocusAttributes(flag);
1420 }
1421
1422 - (void)setWindowHasFocus:(BOOL)flag
1423 {
1424     m_frame->setWindowHasFocus(flag);
1425 }
1426
1427 - (void)setShouldCreateRenderers:(BOOL)f
1428 {
1429     _shouldCreateRenderers = f;
1430 }
1431
1432 - (BOOL)shouldCreateRenderers
1433 {
1434     return _shouldCreateRenderers;
1435 }
1436
1437 - (int)numPendingOrLoadingRequests
1438 {
1439     Document *doc = m_frame->document();
1440     
1441     if (doc)
1442         return KWQNumberOfPendingOrLoadingRequests (doc->docLoader());
1443     return 0;
1444 }
1445
1446 - (BOOL)doneProcessingData
1447 {
1448     Document *doc = m_frame->document();
1449     if (doc) {
1450         Tokenizer* tok = doc->tokenizer();
1451         if (tok)
1452             return !tok->processingData();
1453     }
1454     return YES;
1455 }
1456
1457 - (BOOL)shouldClose
1458 {
1459     return m_frame->shouldClose();
1460 }
1461
1462 - (NSColor *)bodyBackgroundColor
1463 {
1464     return m_frame->bodyBackgroundColor();
1465 }
1466
1467 - (NSColor *)selectionColor
1468 {
1469     RenderCanvas* root = static_cast<RenderCanvas *>(m_frame->document()->renderer());
1470     if (root) {
1471         RenderStyle *pseudoStyle = root->getPseudoStyle(RenderStyle::SELECTION);
1472         if (pseudoStyle && pseudoStyle->backgroundColor().isValid()) {
1473             return nsColor(pseudoStyle->backgroundColor());
1474         }
1475     }
1476     return m_frame->displaysWithFocusAttributes() ? [NSColor selectedTextBackgroundColor] : [NSColor secondarySelectedControlColor];
1477 }
1478
1479 - (void)adjustViewSize
1480 {
1481     FrameView *view = m_frame->view();
1482     if (view)
1483         view->adjustViewSize();
1484 }
1485
1486 - (id)accessibilityTree
1487 {
1488     AccessibilityObjectCache::enableAccessibility();
1489     if (!m_frame || !m_frame->document())
1490         return nil;
1491     RenderCanvas* root = static_cast<RenderCanvas *>(m_frame->document()->renderer());
1492     if (!root)
1493         return nil;
1494     return m_frame->document()->getAccObjectCache()->get(root);
1495 }
1496
1497 - (void)setDrawsBackground:(BOOL)drawsBackground
1498 {
1499     if (m_frame && m_frame->view())
1500         m_frame->view()->setTransparent(!drawsBackground);
1501 }
1502
1503 - (void)undoEditing:(id)arg
1504 {
1505     ASSERT([arg isKindOfClass:[KWQEditCommand class]]);
1506     [arg command]->unapply();
1507 }
1508
1509 - (void)redoEditing:(id)arg
1510 {
1511     ASSERT([arg isKindOfClass:[KWQEditCommand class]]);
1512     [arg command]->reapply();
1513 }
1514
1515 - (DOMRange *)rangeByExpandingSelectionWithGranularity:(WebBridgeSelectionGranularity)granularity
1516 {
1517     if (!m_frame->hasSelection())
1518         return nil;
1519         
1520     // NOTE: The enums *must* match the very similar ones declared in SelectionController.h
1521     SelectionController selection(m_frame->selection());
1522     selection.expandUsingGranularity(static_cast<TextGranularity>(granularity));
1523     return [DOMRange _rangeWith:selection.toRange().get()];
1524 }
1525
1526 - (DOMRange *)rangeByAlteringCurrentSelection:(WebSelectionAlteration)alteration direction:(WebBridgeSelectionDirection)direction granularity:(WebBridgeSelectionGranularity)granularity
1527 {
1528     if (!m_frame->hasSelection())
1529         return nil;
1530         
1531     // NOTE: The enums *must* match the very similar ones declared in SelectionController.h
1532     SelectionController selection(m_frame->selection());
1533     selection.modify(static_cast<SelectionController::EAlter>(alteration), 
1534                      static_cast<SelectionController::EDirection>(direction), 
1535                      static_cast<TextGranularity>(granularity));
1536     return [DOMRange _rangeWith:selection.toRange().get()];
1537 }
1538
1539 - (void)alterCurrentSelection:(WebSelectionAlteration)alteration direction:(WebBridgeSelectionDirection)direction granularity:(WebBridgeSelectionGranularity)granularity
1540 {
1541     if (!m_frame->hasSelection())
1542         return;
1543         
1544     // NOTE: The enums *must* match the very similar ones declared in SelectionController.h
1545     SelectionController selection(m_frame->selection());
1546     selection.modify(static_cast<SelectionController::EAlter>(alteration), 
1547                      static_cast<SelectionController::EDirection>(direction), 
1548                      static_cast<TextGranularity>(granularity));
1549
1550     // save vertical navigation x position if necessary; many types of motion blow it away
1551     int xPos = Frame::NoXPosForVerticalArrowNavigation;
1552     switch (granularity) {
1553         case WebBridgeSelectByLine:
1554         case WebBridgeSelectByParagraph:
1555             xPos = m_frame->xPosForVerticalArrowNavigation();
1556             break;
1557         case WebBridgeSelectByCharacter:
1558         case WebBridgeSelectByWord:
1559         case WebBridgeSelectBySentence:
1560         case WebBridgeSelectToLineBoundary:
1561         case WebBridgeSelectToParagraphBoundary:
1562         case WebBridgeSelectToSentenceBoundary:
1563         case WebBridgeSelectToDocumentBoundary:
1564             break;
1565     }
1566
1567     
1568     // setting the selection always clears saved vertical navigation x position
1569     m_frame->setSelection(selection);
1570     
1571     // altering the selection also sets the granularity back to character
1572     // NOTE: The one exception is that we need to keep word granularity
1573     // to preserve smart delete behavior when extending by word.  e.g. double-click,
1574     // then shift-option-rightarrow, then delete needs to smart delete, per TextEdit.
1575     if (!((alteration == WebSelectByExtending) &&
1576           (granularity == WebBridgeSelectByWord) && (m_frame->selectionGranularity() == WordGranularity)))
1577         m_frame->setSelectionGranularity(static_cast<TextGranularity>(WebBridgeSelectByCharacter));
1578     
1579     // restore vertical navigation x position if necessary
1580     if (xPos != Frame::NoXPosForVerticalArrowNavigation)
1581         m_frame->setXPosForVerticalArrowNavigation(xPos);
1582
1583     m_frame->selectFrameElementInParentIfFullySelected();
1584
1585     [self ensureSelectionVisible];
1586 }
1587
1588 - (DOMRange *)rangeByAlteringCurrentSelection:(WebSelectionAlteration)alteration verticalDistance:(float)verticalDistance
1589 {
1590     if (!m_frame->hasSelection())
1591         return nil;
1592         
1593     SelectionController selection(m_frame->selection());
1594     selection.modify(static_cast<SelectionController::EAlter>(alteration), static_cast<int>(verticalDistance));
1595     return [DOMRange _rangeWith:selection.toRange().get()];
1596 }
1597
1598 - (void)alterCurrentSelection:(WebSelectionAlteration)alteration verticalDistance:(float)verticalDistance
1599 {
1600     if (!m_frame->hasSelection())
1601         return;
1602         
1603     SelectionController selection(m_frame->selection());
1604     selection.modify(static_cast<SelectionController::EAlter>(alteration), static_cast<int>(verticalDistance));
1605
1606     // setting the selection always clears saved vertical navigation x position, so preserve it
1607     int xPos = m_frame->xPosForVerticalArrowNavigation();
1608     m_frame->setSelection(selection);
1609     m_frame->setSelectionGranularity(static_cast<TextGranularity>(WebBridgeSelectByCharacter));
1610     m_frame->setXPosForVerticalArrowNavigation(xPos);
1611
1612     m_frame->selectFrameElementInParentIfFullySelected();
1613
1614     [self ensureSelectionVisible];
1615 }
1616
1617 - (WebBridgeSelectionGranularity)selectionGranularity
1618 {
1619     // NOTE: The enums *must* match the very similar ones declared in SelectionController.h
1620     return static_cast<WebBridgeSelectionGranularity>(m_frame->selectionGranularity());
1621 }
1622
1623 - (void)setSelectedDOMRange:(DOMRange *)range affinity:(NSSelectionAffinity)selectionAffinity closeTyping:(BOOL)closeTyping
1624 {
1625     Node *startContainer = [[range startContainer] _node];
1626     Node *endContainer = [[range endContainer] _node];
1627     ASSERT(startContainer);
1628     ASSERT(endContainer);
1629     ASSERT(startContainer->document() == endContainer->document());
1630     
1631     m_frame->document()->updateLayoutIgnorePendingStylesheets();
1632
1633     EAffinity affinity = static_cast<EAffinity>(selectionAffinity);
1634     
1635     // Non-collapsed ranges are not allowed to start at the end of a line that is wrapped,
1636     // they start at the beginning of the next line instead
1637     if (![range collapsed])
1638         affinity = DOWNSTREAM;
1639     
1640     // FIXME: Can we provide extentAffinity?
1641     VisiblePosition visibleStart(startContainer, [range startOffset], affinity);
1642     VisiblePosition visibleEnd(endContainer, [range endOffset], SEL_DEFAULT_AFFINITY);
1643     SelectionController selection(visibleStart, visibleEnd);
1644     m_frame->setSelection(selection, closeTyping);
1645 }
1646
1647 - (DOMRange *)selectedDOMRange
1648 {
1649     return [DOMRange _rangeWith:m_frame->selection().toRange().get()];
1650 }
1651
1652 - (NSRange)convertToNSRange:(Range *)range
1653 {
1654     if (!range || range->isDetached()) {
1655         return NSMakeRange(NSNotFound, 0);
1656     }
1657
1658     RefPtr<Range> fromStartRange(m_frame->document()->createRange());
1659     int exception = 0;
1660
1661     fromStartRange->setEnd(range->startContainer(exception), range->startOffset(exception), exception);
1662     int startPosition = TextIterator::rangeLength(fromStartRange.get());
1663
1664     fromStartRange->setEnd(range->endContainer(exception), range->endOffset(exception), exception);
1665     int endPosition = TextIterator::rangeLength(fromStartRange.get());
1666
1667     return NSMakeRange(startPosition, endPosition - startPosition);
1668 }
1669
1670 - (PassRefPtr<Range>)convertToDOMRange:(NSRange)nsrange
1671 {
1672     if (nsrange.location > INT_MAX)
1673         return 0;
1674     if (nsrange.length > INT_MAX || nsrange.location + nsrange.length > INT_MAX)
1675         nsrange.length = INT_MAX - nsrange.location;
1676
1677     return TextIterator::rangeFromLocationAndLength(m_frame->document(), nsrange.location, nsrange.length);
1678 }
1679
1680 - (DOMRange *)convertNSRangeToDOMRange:(NSRange)nsrange
1681 {
1682     return [DOMRange _rangeWith:[self convertToDOMRange:nsrange].get()];
1683 }
1684
1685 - (NSRange)convertDOMRangeToNSRange:(DOMRange *)range
1686 {
1687     return [self convertToNSRange:[range _range]];
1688 }
1689
1690 - (void)selectNSRange:(NSRange)range
1691 {
1692     m_frame->setSelection(SelectionController([self convertToDOMRange:range].get(), SEL_DEFAULT_AFFINITY));
1693 }
1694
1695 - (NSRange)selectedNSRange
1696 {
1697     return [self convertToNSRange:m_frame->selection().toRange().get()];
1698 }
1699
1700 - (NSSelectionAffinity)selectionAffinity
1701 {
1702     return static_cast<NSSelectionAffinity>(m_frame->selection().affinity());
1703 }
1704
1705 - (void)setMarkDOMRange:(DOMRange *)range
1706 {
1707     Range* r = [range _range];
1708     m_frame->setMark(Selection(startPosition(r), endPosition(r), SEL_DEFAULT_AFFINITY));
1709 }
1710
1711 - (DOMRange *)markDOMRange
1712 {
1713     return [DOMRange _rangeWith:m_frame->mark().toRange().get()];
1714 }
1715
1716 - (void)setMarkedTextDOMRange:(DOMRange *)range customAttributes:(NSArray *)attributes ranges:(NSArray *)ranges
1717 {
1718     m_frame->setMarkedTextRange([range _range], attributes, ranges);
1719 }
1720
1721 - (DOMRange *)markedTextDOMRange
1722 {
1723     return [DOMRange _rangeWith:m_frame->markedTextRange()];
1724 }
1725
1726 - (NSRange)markedTextNSRange
1727 {
1728     return [self convertToNSRange:m_frame->markedTextRange()];
1729 }
1730
1731 - (void)replaceMarkedTextWithText:(NSString *)text
1732 {
1733     if (!m_frame->hasSelection())
1734         return;
1735     
1736     int exception = 0;
1737
1738     Range *markedTextRange = m_frame->markedTextRange();
1739     if (markedTextRange && !markedTextRange->collapsed(exception))
1740         TypingCommand::deleteKeyPressed(m_frame->document(), NO);
1741     
1742     if ([text length] > 0)
1743         TypingCommand::insertText(m_frame->document(), text, YES);
1744     
1745     [self ensureSelectionVisible];
1746 }
1747
1748 - (BOOL)canDeleteRange:(DOMRange *)range
1749 {
1750     Node *startContainer = [[range startContainer] _node];
1751     Node *endContainer = [[range endContainer] _node];
1752     if (startContainer == nil || endContainer == nil)
1753         return NO;
1754     
1755     if (!startContainer->isContentEditable() || !endContainer->isContentEditable())
1756         return NO;
1757     
1758     if ([range collapsed]) {
1759         VisiblePosition start(startContainer, [range startOffset], DOWNSTREAM);
1760         if (isStartOfEditableContent(start))
1761             return NO;
1762     }
1763     
1764     return YES;
1765 }
1766
1767 // Given proposedRange, returns an extended range that includes adjacent whitespace that should
1768 // be deleted along with the proposed range in order to preserve proper spacing and punctuation of
1769 // the text surrounding the deletion.
1770 - (DOMRange *)smartDeleteRangeForProposedRange:(DOMRange *)proposedRange
1771 {
1772     Node *startContainer = [[proposedRange startContainer] _node];
1773     Node *endContainer = [[proposedRange endContainer] _node];
1774     if (startContainer == nil || endContainer == nil)
1775         return nil;
1776
1777     ASSERT(startContainer->document() == endContainer->document());
1778     
1779     m_frame->document()->updateLayoutIgnorePendingStylesheets();
1780
1781     Position start(startContainer, [proposedRange startOffset]);
1782     Position end(endContainer, [proposedRange endOffset]);
1783     Position newStart = start.upstream().leadingWhitespacePosition(DOWNSTREAM, true);
1784     if (newStart.isNull())
1785         newStart = start;
1786     Position newEnd = end.downstream().trailingWhitespacePosition(DOWNSTREAM, true);
1787     if (newEnd.isNull())
1788         newEnd = end;
1789
1790     RefPtr<Range> range = m_frame->document()->createRange();
1791     int exception = 0;
1792     range->setStart(newStart.node(), newStart.offset(), exception);
1793     range->setEnd(newStart.node(), newStart.offset(), exception);
1794     return [DOMRange _rangeWith:range.get()];
1795 }
1796
1797 // Determines whether whitespace needs to be added around aString to preserve proper spacing and
1798 // punctuation when itÕs inserted into the receiverÕs text over charRange. Returns by reference
1799 // in beforeString and afterString any whitespace that should be added, unless either or both are
1800 // nil. Both are returned as nil if aString is nil or if smart insertion and deletion are disabled.
1801 - (void)smartInsertForString:(NSString *)pasteString replacingRange:(DOMRange *)rangeToReplace beforeString:(NSString **)beforeString afterString:(NSString **)afterString
1802 {
1803     // give back nil pointers in case of early returns
1804     if (beforeString)
1805         *beforeString = nil;
1806     if (afterString)
1807         *afterString = nil;
1808         
1809     // inspect destination
1810     Node *startContainer = [[rangeToReplace startContainer] _node];
1811     Node *endContainer = [[rangeToReplace endContainer] _node];
1812
1813     Position startPos(startContainer, [rangeToReplace startOffset]);
1814     Position endPos(endContainer, [rangeToReplace endOffset]);
1815
1816     VisiblePosition startVisiblePos = VisiblePosition(startPos, VP_DEFAULT_AFFINITY);
1817     VisiblePosition endVisiblePos = VisiblePosition(endPos, VP_DEFAULT_AFFINITY);
1818     
1819     // this check also ensures startContainer, startPos, endContainer, and endPos are non-null
1820     if (startVisiblePos.isNull() || endVisiblePos.isNull())
1821         return;
1822
1823     bool addLeadingSpace = startPos.leadingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isStartOfParagraph(startVisiblePos);
1824     if (addLeadingSpace) {
1825         QChar previousChar = startVisiblePos.previous().characterAfter();
1826         if (previousChar.unicode())
1827             addLeadingSpace = !m_frame->isCharacterSmartReplaceExempt(previousChar, true);
1828     }
1829     
1830     bool addTrailingSpace = endPos.trailingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isEndOfParagraph(endVisiblePos);
1831     if (addTrailingSpace) {
1832         QChar thisChar = endVisiblePos.characterAfter();
1833         if (thisChar.unicode())
1834             addTrailingSpace = !m_frame->isCharacterSmartReplaceExempt(thisChar, false);
1835     }
1836     
1837     // inspect source
1838     bool hasWhitespaceAtStart = false;
1839     bool hasWhitespaceAtEnd = false;
1840     unsigned pasteLength = [pasteString length];
1841     if (pasteLength > 0) {
1842         NSCharacterSet *whiteSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
1843         
1844         if ([whiteSet characterIsMember:[pasteString characterAtIndex:0]]) {
1845             hasWhitespaceAtStart = YES;
1846         }
1847         if ([whiteSet characterIsMember:[pasteString characterAtIndex:(pasteLength - 1)]]) {
1848             hasWhitespaceAtEnd = YES;
1849         }
1850     }
1851     
1852     // issue the verdict
1853     if (beforeString && addLeadingSpace && !hasWhitespaceAtStart)
1854         *beforeString = @" ";
1855     if (afterString && addTrailingSpace && !hasWhitespaceAtEnd)
1856         *afterString = @" ";
1857 }
1858
1859 - (DOMDocumentFragment *)documentFragmentWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString 
1860 {
1861     if (!m_frame || !m_frame->document())
1862         return 0;
1863
1864     return [DOMDocumentFragment _documentFragmentWith:createFragmentFromMarkup(m_frame->document(),
1865         DeprecatedString::fromNSString(markupString), DeprecatedString::fromNSString(baseURLString)).get()];
1866 }
1867
1868 - (DOMDocumentFragment *)documentFragmentWithText:(NSString *)text
1869 {
1870     if (!m_frame || !m_frame->document() || !text)
1871         return 0;
1872     
1873     return [DOMDocumentFragment _documentFragmentWith:createFragmentFromText(m_frame->document(), DeprecatedString::fromNSString(text)).get()];
1874 }
1875
1876 - (DOMDocumentFragment *)documentFragmentWithNodesAsParagraphs:(NSArray *)nodes
1877 {
1878     NSEnumerator *nodeEnum = [nodes objectEnumerator];
1879     DOMNode *node;
1880     DeprecatedPtrList<Node> nodeList;
1881     
1882     if (!m_frame || !m_frame->document())
1883         return 0;
1884     
1885     while ((node = [nodeEnum nextObject])) {
1886         nodeList.append([node _node]);
1887     }
1888     
1889     return [DOMDocumentFragment _documentFragmentWith:createFragmentFromNodeList(m_frame->document(), nodeList).get()];
1890 }
1891
1892 - (void)replaceSelectionWithFragment:(DOMDocumentFragment *)fragment selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle
1893 {
1894     if (!m_frame->hasSelection() || !fragment)
1895         return;
1896     
1897     EditCommandPtr(new ReplaceSelectionCommand(m_frame->document(), [fragment _fragment], selectReplacement, smartReplace, matchStyle)).apply();
1898     [self ensureSelectionVisible];
1899 }
1900
1901 - (void)replaceSelectionWithNode:(DOMNode *)node selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1902 {
1903     DOMDocumentFragment *fragment = [[self DOMDocument] createDocumentFragment];
1904     [fragment appendChild:node];
1905     [self replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:NO];
1906 }
1907
1908 - (void)replaceSelectionWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1909 {
1910     DOMDocumentFragment *fragment = [self documentFragmentWithMarkupString:markupString baseURLString:baseURLString];
1911     [self replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:NO];
1912 }
1913
1914 - (void)replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1915 {
1916     [self replaceSelectionWithFragment:[self documentFragmentWithText:text] selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:YES];
1917 }
1918
1919 - (bool)canIncreaseSelectionListLevel
1920 {
1921     return ModifySelectionListLevelCommand::canIncreaseSelectionListLevel(m_frame->document());
1922 }
1923
1924 - (bool)canDecreaseSelectionListLevel
1925 {
1926     return ModifySelectionListLevelCommand::canDecreaseSelectionListLevel(m_frame->document());
1927 }
1928
1929 - (void)increaseSelectionListLevel
1930 {
1931     if (!m_frame->hasSelection())
1932         return;
1933     
1934     ModifySelectionListLevelCommand::increaseSelectionListLevel(m_frame->document());
1935     [self ensureSelectionVisible];
1936 }
1937
1938 - (void)decreaseSelectionListLevel
1939 {
1940     if (!m_frame->hasSelection())
1941         return;
1942     
1943     ModifySelectionListLevelCommand::decreaseSelectionListLevel(m_frame->document());
1944     [self ensureSelectionVisible];
1945 }
1946
1947 - (void)insertLineBreak
1948 {
1949     if (!m_frame->hasSelection())
1950         return;
1951     
1952     TypingCommand::insertLineBreak(m_frame->document());
1953     [self ensureSelectionVisible];
1954 }
1955
1956 - (void)insertParagraphSeparator
1957 {
1958     if (!m_frame->hasSelection())
1959         return;
1960     
1961     TypingCommand::insertParagraphSeparator(m_frame->document());
1962     [self ensureSelectionVisible];
1963 }
1964
1965 - (void)insertParagraphSeparatorInQuotedContent
1966 {
1967     if (!m_frame->hasSelection())
1968         return;
1969     
1970     TypingCommand::insertParagraphSeparatorInQuotedContent(m_frame->document());
1971     [self ensureSelectionVisible];
1972 }
1973
1974 - (void)insertText:(NSString *)text selectInsertedText:(BOOL)selectInsertedText
1975 {
1976     if (!m_frame->hasSelection())
1977         return;
1978     
1979     TypingCommand::insertText(m_frame->document(), text, selectInsertedText);
1980     [self ensureSelectionVisible];
1981 }
1982
1983 - (void)setSelectionToDragCaret
1984 {
1985     m_frame->setSelection(m_frame->dragCaret());
1986 }
1987
1988 - (void)moveSelectionToDragCaret:(DOMDocumentFragment *)selectionFragment smartMove:(BOOL)smartMove
1989 {
1990     Position base = m_frame->dragCaret().base();
1991     EditCommandPtr(new MoveSelectionCommand(m_frame->document(), [selectionFragment _fragment], base, smartMove)).apply();
1992 }
1993
1994 - (VisiblePosition)_visiblePositionForPoint:(NSPoint)point
1995 {
1996     RenderObject *renderer = m_frame->renderer();
1997     if (!renderer) {
1998         return VisiblePosition();
1999     }
2000     
2001     RenderObject::NodeInfo nodeInfo = [self nodeInfoAtPoint:point allowShadowContent:YES];
2002     
2003     Node *node = nodeInfo.innerNode();
2004     if (!node || !node->renderer())
2005         return VisiblePosition();
2006     
2007     return node->renderer()->positionForCoordinates((int)point.x, (int)point.y);
2008 }
2009
2010 - (void)moveDragCaretToPoint:(NSPoint)point
2011 {   
2012     SelectionController dragCaret([self _visiblePositionForPoint:point]);
2013     m_frame->setDragCaret(dragCaret);
2014 }
2015
2016 - (void)removeDragCaret
2017 {
2018     m_frame->setDragCaret(SelectionController());
2019 }
2020
2021 - (DOMRange *)dragCaretDOMRange
2022 {
2023     return [DOMRange _rangeWith:m_frame->dragCaret().toRange().get()];
2024 }
2025
2026 - (BOOL)isDragCaretRichlyEditable
2027 {
2028     return m_frame->dragCaret().isContentRichlyEditable();
2029 }
2030
2031 - (DOMRange *)editableDOMRangeForPoint:(NSPoint)point
2032 {
2033     VisiblePosition position = [self _visiblePositionForPoint:point];
2034     return position.isNull() ? nil : [DOMRange _rangeWith:SelectionController(position).toRange().get()];
2035 }
2036
2037 - (DOMRange *)characterRangeAtPoint:(NSPoint)point
2038 {
2039     VisiblePosition position = [self _visiblePositionForPoint:point];
2040     if (position.isNull())
2041         return nil;
2042     
2043     VisiblePosition previous = position.previous();
2044     if (previous.isNotNull()) {
2045         DOMRange *previousCharacterRange = [DOMRange _rangeWith:makeRange(previous, position).get()];
2046         NSRect rect = [self firstRectForDOMRange:previousCharacterRange];
2047         if (NSPointInRect(point, rect))
2048             return previousCharacterRange;
2049     }
2050
2051     VisiblePosition next = position.next();
2052     if (next.isNotNull()) {
2053         DOMRange *nextCharacterRange = [DOMRange _rangeWith:makeRange(position, next).get()];
2054         NSRect rect = [self firstRectForDOMRange:nextCharacterRange];
2055         if (NSPointInRect(point, rect))
2056             return nextCharacterRange;
2057     }
2058     
2059     return nil;
2060 }
2061
2062 - (void)deleteSelectionWithSmartDelete:(BOOL)smartDelete
2063 {
2064     if (!m_frame->hasSelection())
2065         return;
2066     
2067     EditCommandPtr(new DeleteSelectionCommand(m_frame->document(), smartDelete)).apply();
2068 }
2069
2070 - (void)deleteKeyPressedWithSmartDelete:(BOOL)smartDelete
2071 {
2072     if (!m_frame || !m_frame->document())
2073         return;
2074     
2075     TypingCommand::deleteKeyPressed(m_frame->document(), smartDelete);
2076     [self ensureSelectionVisible];
2077 }
2078
2079 - (void)forwardDeleteKeyPressedWithSmartDelete:(BOOL)smartDelete
2080 {
2081     if (!m_frame || !m_frame->document())
2082         return;
2083     
2084     TypingCommand::forwardDeleteKeyPressed(m_frame->document(), smartDelete);
2085     [self ensureSelectionVisible];
2086 }
2087
2088 - (DOMCSSStyleDeclaration *)typingStyle
2089 {
2090     if (!m_frame || !m_frame->typingStyle())
2091         return nil;
2092     return [DOMCSSStyleDeclaration _styleDeclarationWith:m_frame->typingStyle()->copy().get()];
2093 }
2094
2095 - (void)setTypingStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(WebUndoAction)undoAction
2096 {
2097     if (!m_frame)
2098         return;
2099     m_frame->computeAndSetTypingStyle([style _styleDeclaration], static_cast<EditAction>(undoAction));
2100 }
2101
2102 - (void)applyStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(WebUndoAction)undoAction
2103 {
2104     if (!m_frame)
2105         return;
2106     m_frame->applyStyle([style _styleDeclaration], static_cast<EditAction>(undoAction));
2107 }
2108
2109 - (void)applyParagraphStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(WebUndoAction)undoAction
2110 {
2111     if (!m_frame)
2112         return;
2113     m_frame->applyParagraphStyle([style _styleDeclaration], static_cast<EditAction>(undoAction));
2114 }
2115
2116 - (BOOL)selectionStartHasStyle:(DOMCSSStyleDeclaration *)style
2117 {
2118     if (!m_frame)
2119         return NO;
2120     return m_frame->selectionStartHasStyle([style _styleDeclaration]);
2121 }
2122
2123 - (NSCellStateValue)selectionHasStyle:(DOMCSSStyleDeclaration *)style
2124 {
2125     if (!m_frame)
2126         return NSOffState;
2127     switch (m_frame->selectionHasStyle([style _styleDeclaration])) {
2128         case Frame::falseTriState:
2129             return NSOffState;
2130         case Frame::trueTriState:
2131             return NSOnState;
2132         case Frame::mixedTriState:
2133             return NSMixedState;
2134     }
2135     return NSOffState;
2136 }
2137
2138 - (void)applyEditingStyleToBodyElement
2139 {
2140     if (!m_frame)
2141         return;
2142     m_frame->applyEditingStyleToBodyElement();
2143 }
2144
2145 - (void)removeEditingStyleFromBodyElement
2146 {
2147     if (!m_frame)
2148         return;
2149     m_frame->removeEditingStyleFromBodyElement();
2150 }
2151
2152 - (void)applyEditingStyleToElement:(DOMElement *)element
2153 {
2154     if (!m_frame)
2155         return;
2156     m_frame->applyEditingStyleToElement([element _element]);
2157 }
2158
2159 - (void)removeEditingStyleFromElement:(DOMElement *)element
2160 {
2161     if (!m_frame)
2162         return;
2163     m_frame->removeEditingStyleFromElement([element _element]);
2164 }
2165
2166 - (NSFont *)fontForSelection:(BOOL *)hasMultipleFonts
2167 {
2168     bool multipleFonts = false;
2169     NSFont *font = nil;
2170     if (m_frame)
2171         font = m_frame->fontForSelection(hasMultipleFonts ? &multipleFonts : 0);
2172     if (hasMultipleFonts)
2173         *hasMultipleFonts = multipleFonts;
2174     return font;
2175 }
2176
2177 - (NSDictionary *)fontAttributesForSelectionStart
2178 {
2179     return m_frame ? m_frame->fontAttributesForSelectionStart() : nil;
2180 }
2181
2182 - (NSWritingDirection)baseWritingDirectionForSelectionStart
2183 {
2184     // FIXME: remove this NSWritingDirection cast once <rdar://problem/4509035> is fixed
2185     return m_frame ? m_frame->baseWritingDirectionForSelectionStart() : (NSWritingDirection)NSWritingDirectionLeftToRight;
2186 }
2187
2188 - (void)ensureSelectionVisible
2189 {
2190     if (!m_frame->hasSelection())
2191         return;
2192     
2193     FrameView *v = m_frame->view();
2194     if (!v)
2195         return;
2196
2197     Position extent = m_frame->selection().extent();
2198     if (extent.isNull())
2199         return;
2200     
2201     RenderObject *renderer = extent.node()->renderer();
2202     if (!renderer)
2203         return;
2204     
2205     NSView *documentView = v->getDocumentView();
2206     if (!documentView)
2207         return;
2208     
2209     IntRect extentRect = renderer->caretRect(extent.offset(), m_frame->selection().affinity());
2210     RenderLayer *layer = renderer->enclosingLayer();
2211     if (layer)
2212         layer->scrollRectToVisible(extentRect, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignToEdgeIfNeeded);
2213 }
2214
2215 // [info draggingLocation] is in window coords
2216
2217 - (BOOL)eventMayStartDrag:(NSEvent *)event
2218 {
2219     return m_frame ? m_frame->eventMayStartDrag(event) : NO;
2220 }
2221
2222 static IntPoint globalPoint(NSWindow* window, NSPoint windowPoint)
2223 {
2224     NSPoint screenPoint = [window convertBaseToScreen:windowPoint];
2225     return IntPoint((int)screenPoint.x, (int)(NSMaxY([[[NSScreen screens] objectAtIndex:0] frame]) - screenPoint.y));
2226 }
2227
2228 static PlatformMouseEvent createMouseEventFromDraggingInfo(NSWindow* window, id <NSDraggingInfo> info)
2229 {
2230     // FIXME: Fake modifier keys here.
2231     return PlatformMouseEvent(IntPoint([info draggingLocation]), globalPoint(window, [info draggingLocation]),
2232         LeftButton, 0, false, false, false, false);
2233 }
2234
2235 - (NSDragOperation)dragOperationForDraggingInfo:(id <NSDraggingInfo>)info
2236 {
2237     NSDragOperation op = NSDragOperationNone;
2238     if (m_frame) {
2239         RefPtr<FrameView> v = m_frame->view();
2240         if (v) {
2241             ClipboardMac::AccessPolicy policy = m_frame->baseURL().isLocalFile() ? ClipboardMac::Readable : ClipboardMac::TypesReadable;
2242             RefPtr<ClipboardMac> clipboard = new ClipboardMac(true, [info draggingPasteboard], policy);
2243             NSDragOperation srcOp = [info draggingSourceOperationMask];
2244             clipboard->setSourceOperation(srcOp);
2245
2246             PlatformMouseEvent event = createMouseEventFromDraggingInfo([self window], info);
2247             if (v->updateDragAndDrop(event, clipboard.get())) {
2248                 // *op unchanged if no source op was set
2249                 if (!clipboard->destinationOperation(&op)) {
2250                     // The element accepted but they didn't pick an operation, so we pick one for them
2251                     // (as does WinIE).
2252                     if (srcOp & NSDragOperationCopy) {
2253                         op = NSDragOperationCopy;
2254                     } else if (srcOp & NSDragOperationMove || srcOp & NSDragOperationGeneric) {
2255                         op = NSDragOperationMove;
2256                     } else if (srcOp & NSDragOperationLink) {
2257                         op = NSDragOperationLink;
2258                     } else {
2259                         op = NSDragOperationGeneric;
2260                     }
2261                 } else if (!(op & srcOp)) {
2262                     // make sure WC picked an op that was offered.  Cocoa doesn't seem to enforce this,
2263                     // but IE does.
2264                     op = NSDragOperationNone;
2265                 }
2266             }
2267             clipboard->setAccessPolicy(ClipboardMac::Numb);    // invalidate clipboard here for security
2268             return op;
2269         }
2270     }
2271     return op;
2272 }
2273
2274 - (void)dragExitedWithDraggingInfo:(id <NSDraggingInfo>)info
2275 {
2276     if (m_frame) {
2277         RefPtr<FrameView> v = m_frame->view();
2278         if (v) {
2279             // Sending an event can result in the destruction of the view and part.
2280             ClipboardMac::AccessPolicy policy = m_frame->baseURL().isLocalFile() ? ClipboardMac::Readable : ClipboardMac::TypesReadable;
2281             RefPtr<ClipboardMac> clipboard = new ClipboardMac(true, [info draggingPasteboard], policy);
2282             clipboard->setSourceOperation([info draggingSourceOperationMask]);            
2283             v->cancelDragAndDrop(createMouseEventFromDraggingInfo([self window], info), clipboard.get());
2284             clipboard->setAccessPolicy(ClipboardMac::Numb);    // invalidate clipboard here for security
2285         }
2286     }
2287 }
2288
2289 - (BOOL)concludeDragForDraggingInfo:(id <NSDraggingInfo>)info
2290 {
2291     if (m_frame) {
2292         RefPtr<FrameView> v = m_frame->view();
2293         if (v) {
2294             // Sending an event can result in the destruction of the view and part.
2295             RefPtr<ClipboardMac> clipboard = new ClipboardMac(true, [info draggingPasteboard], ClipboardMac::Readable);
2296             clipboard->setSourceOperation([info draggingSourceOperationMask]);
2297             BOOL result = v->performDragAndDrop(createMouseEventFromDraggingInfo([self window], info), clipboard.get());
2298             clipboard->setAccessPolicy(ClipboardMac::Numb);    // invalidate clipboard here for security
2299             return result;
2300         }
2301     }
2302     return NO;
2303 }
2304
2305 - (void)dragSourceMovedTo:(NSPoint)windowLoc
2306 {
2307     if (m_frame) {
2308         // FIXME: Fake modifier keys here.
2309         PlatformMouseEvent event(IntPoint(windowLoc), globalPoint([self window], windowLoc),
2310             LeftButton, 0, false, false, false, false);
2311         m_frame->dragSourceMovedTo(event);
2312     }
2313 }
2314
2315 - (void)dragSourceEndedAt:(NSPoint)windowLoc operation:(NSDragOperation)operation
2316 {
2317     if (m_frame) {
2318         // FIXME: Fake modifier keys here.
2319         PlatformMouseEvent event(IntPoint(windowLoc), globalPoint([self window], windowLoc),
2320             LeftButton, 0, false, false, false, false);
2321         m_frame->dragSourceEndedAt(event, operation);
2322     }
2323 }
2324
2325 - (BOOL)mayDHTMLCut
2326 {
2327     return m_frame->mayCut();
2328 }
2329
2330 - (BOOL)mayDHTMLCopy
2331 {
2332     return m_frame->mayCopy();
2333 }
2334
2335 - (BOOL)mayDHTMLPaste
2336 {
2337     return m_frame->mayPaste();
2338 }
2339
2340 - (BOOL)tryDHTMLCut
2341 {
2342     return m_frame->tryCut();
2343 }
2344
2345 - (BOOL)tryDHTMLCopy
2346 {
2347     return m_frame->tryCopy();
2348 }
2349
2350 - (BOOL)tryDHTMLPaste
2351 {
2352     return m_frame->tryPaste();
2353 }
2354
2355 - (DOMRange *)rangeOfCharactersAroundCaret
2356 {
2357     if (!m_frame)
2358         return nil;
2359         
2360     SelectionController selection(m_frame->selection());
2361     if (!selection.isCaret())
2362         return nil;
2363
2364     VisiblePosition caret(selection.start(), selection.affinity());
2365     VisiblePosition next = caret.next();
2366     VisiblePosition previous = caret.previous();
2367     if (previous.isNull() || next.isNull() || caret == next || caret == previous)
2368         return nil;
2369
2370     return [DOMRange _rangeWith:makeRange(previous, next).get()];
2371 }
2372
2373 - (NSMutableDictionary *)dashboardRegions
2374 {
2375     return m_frame->dashboardRegionsDictionary();
2376 }
2377
2378 // FIXME: The following 2 functions are copied from AppKit. It would be best share code.
2379
2380 // MF:!!! For now we will use static character sets for the computation, but we should eventually probably make these keys in the language dictionaries.
2381 // MF:!!! The following characters (listed with their nextstep encoding values) were in the preSmartTable in the old text objet, but aren't yet in the new text object: NS_FIGSPACE (0x80), exclamdown (0xa1), sterling (0xa3), yen (0xa5), florin (0xa6) section (0xa7), currency (0xa8), quotesingle (0xa9), quotedblleft (0xaa), guillemotleft (0xab), guilsinglleft (0xac), endash (0xb1), quotesinglbase (0xb8), quotedblbase (0xb9), questiondown (0xbf), emdash (0xd0), plusminus (0xd1).
2382 // MF:!!! The following characters (listed with their nextstep encoding values) were in the postSmartTable in the old text objet, but aren't yet in the new text object: NS_FIGSPACE (0x80), cent (0xa2), guilsinglright (0xad), registered (0xb0), dagger (0xa2), daggerdbl (0xa3), endash (0xb1), quotedblright (0xba), guillemotright (0xbb), perthousand (0xbd), onesuperior (0xc0), twosuperior (0xc9), threesuperior (0xcc), emdash (0xd0), ordfeminine (0xe3), ordmasculine (0xeb).
2383 // MF:!!! Another difference in both of these sets from the old text object is we include all the whitespace in whitespaceAndNewlineCharacterSet.
2384 #define _preSmartString @"([\"\'#$/-`{"
2385 #define _postSmartString @")].,;:?\'!\"%*-/}"
2386
2387 static NSCharacterSet *_getPreSmartSet(void)
2388 {
2389     static NSMutableCharacterSet *_preSmartSet = nil;
2390     if (!_preSmartSet) {
2391         _preSmartSet = [[NSMutableCharacterSet characterSetWithCharactersInString:_preSmartString] retain];
2392         [_preSmartSet formUnionWithCharacterSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
2393         // Adding CJK ranges
2394         [_preSmartSet addCharactersInRange:NSMakeRange(0x1100, 256)]; // Hangul Jamo (0x1100 - 0x11FF)
2395         [_preSmartSet addCharactersInRange:NSMakeRange(0x2E80, 352)]; // CJK & Kangxi Radicals (0x2E80 - 0x2FDF)
2396         [_preSmartSet addCharactersInRange:NSMakeRange(0x2FF0, 464)]; // Ideograph Descriptions, CJK Symbols, Hiragana, Katakana, Bopomofo, Hangul Compatibility Jamo, Kanbun, & Bopomofo Ext (0x2FF0 - 0x31BF)
2397         [_preSmartSet addCharactersInRange:NSMakeRange(0x3200, 29392)]; // Enclosed CJK, CJK Ideographs (Uni Han & Ext A), & Yi (0x3200 - 0xA4CF)
2398         [_preSmartSet addCharactersInRange:NSMakeRange(0xAC00, 11183)]; // Hangul Syllables (0xAC00 - 0xD7AF)
2399         [_preSmartSet addCharactersInRange:NSMakeRange(0xF900, 352)]; // CJK Compatibility Ideographs (0xF900 - 0xFA5F)
2400         [_preSmartSet addCharactersInRange:NSMakeRange(0xFE30, 32)]; // CJK Compatibility From (0xFE30 - 0xFE4F)
2401         [_preSmartSet addCharactersInRange:NSMakeRange(0xFF00, 240)]; // Half/Full Width Form (0xFF00 - 0xFFEF)
2402         [_preSmartSet addCharactersInRange:NSMakeRange(0x20000, 0xA6D7)]; // CJK Ideograph Exntension B
2403         [_preSmartSet addCharactersInRange:NSMakeRange(0x2F800, 0x021E)]; // CJK Compatibility Ideographs (0x2F800 - 0x2FA1D)
2404     }
2405     return _preSmartSet;
2406 }
2407
2408 static NSCharacterSet *_getPostSmartSet(void)
2409 {
2410     static NSMutableCharacterSet *_postSmartSet = nil;
2411     if (!_postSmartSet) {
2412         _postSmartSet = [[NSMutableCharacterSet characterSetWithCharactersInString:_postSmartString] retain];
2413         [_postSmartSet formUnionWithCharacterSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
2414         [_postSmartSet addCharactersInRange:NSMakeRange(0x1100, 256)]; // Hangul Jamo (0x1100 - 0x11FF)
2415         [_postSmartSet addCharactersInRange:NSMakeRange(0x2E80, 352)]; // CJK & Kangxi Radicals (0x2E80 - 0x2FDF)
2416         [_postSmartSet addCharactersInRange:NSMakeRange(0x2FF0, 464)]; // Ideograph Descriptions, CJK Symbols, Hiragana, Katakana, Bopomofo, Hangul Compatibility Jamo, Kanbun, & Bopomofo Ext (0x2FF0 - 0x31BF)
2417         [_postSmartSet addCharactersInRange:NSMakeRange(0x3200, 29392)]; // Enclosed CJK, CJK Ideographs (Uni Han & Ext A), & Yi (0x3200 - 0xA4CF)
2418         [_postSmartSet addCharactersInRange:NSMakeRange(0xAC00, 11183)]; // Hangul Syllables (0xAC00 - 0xD7AF)
2419         [_postSmartSet addCharactersInRange:NSMakeRange(0xF900, 352)]; // CJK Compatibility Ideographs (0xF900 - 0xFA5F)
2420         [_postSmartSet addCharactersInRange:NSMakeRange(0xFE30, 32)]; // CJK Compatibility From (0xFE30 - 0xFE4F)
2421         [_postSmartSet addCharactersInRange:NSMakeRange(0xFF00, 240)]; // Half/Full Width Form (0xFF00 - 0xFFEF)
2422         [_postSmartSet addCharactersInRange:NSMakeRange(0x20000, 0xA6D7)]; // CJK Ideograph Exntension B
2423         [_postSmartSet addCharactersInRange:NSMakeRange(0x2F800, 0x021E)]; // CJK Compatibility Ideographs (0x2F800 - 0x2FA1D)        
2424         [_postSmartSet formUnionWithCharacterSet:[NSCharacterSet punctuationCharacterSet]];
2425     }
2426     return _postSmartSet;
2427 }
2428
2429 - (BOOL)isCharacterSmartReplaceExempt:(unichar)c isPreviousCharacter:(BOOL)isPreviousCharacter
2430 {
2431     return [isPreviousCharacter ? _getPreSmartSet() : _getPostSmartSet() characterIsMember:c];
2432 }
2433
2434 - (BOOL)getData:(NSData **)data andResponse:(NSURLResponse **)response forURL:(NSURL *)URL
2435 {
2436     CachedObject* o = [self impl]->document()->docLoader()->cachedObject([URL absoluteString]);
2437     if (!o)
2438         return NO;
2439
2440     *data = o->allData();
2441     *response = o->response();
2442     return YES;
2443 }
2444
2445 - (void)getAllResourceDatas:(NSArray **)datas andResponses:(NSArray **)responses
2446 {
2447     const HashMap<String, CachedObject*>& allResources =  [self impl]->document()->docLoader()->allCachedObjects();
2448     NSMutableArray *d = [[NSMutableArray alloc] initWithCapacity:allResources.size()];
2449     NSMutableArray *r = [[NSMutableArray alloc] initWithCapacity:allResources.size()];
2450     
2451     HashMap<String, CachedObject*>::const_iterator end = allResources.end();
2452     for (HashMap<String, CachedObject*>::const_iterator it = allResources.begin(); it != end; ++it) {
2453         [d addObject:it->second->allData()];
2454         [r addObject:it->second->response()];
2455     }
2456
2457     *datas = [d autorelease];
2458     *responses = [r autorelease];
2459 }
2460
2461 - (BOOL)canProvideDocumentSource
2462 {
2463     String mimeType = m_frame->resourceRequest().m_responseMIMEType;
2464     
2465     if (WebCore::DOMImplementation::isTextMIMEType(mimeType))
2466         return NO;
2467     
2468     return YES;
2469 }
2470
2471 - (BOOL)canSaveAsWebArchive
2472 {
2473     // Currently, all documents that we can view source for
2474     // (HTML and XML documents) can also be saved as web archives
2475     return [self canProvideDocumentSource];
2476 }
2477
2478 @end
2479
2480 @implementation WebCoreFrameBridge (WebCoreBridgeInternal)
2481
2482 - (RootObject *)executionContextForView:(NSView *)aView
2483 {
2484     FrameMac *frame = [self impl];
2485     RootObject *root = new RootObject(aView);    // The root gets deleted by JavaScriptCore.
2486     root->setRootObjectImp(Window::retrieveWindow(frame));
2487     root->setInterpreter(frame->jScript()->interpreter());
2488     frame->addPluginRootObject(root);
2489     return root;
2490 }
2491
2492 - (RenderObject::NodeInfo)nodeInfoAtPoint:(NSPoint)point allowShadowContent:(BOOL)allow
2493 {
2494     return m_frame->nodeInfoAtPoint(IntPoint(point), allow);
2495 }
2496
2497 @end
2498
2499 @implementation WebCoreFrameBridge (WebCoreInternalUse)
2500
2501 - (FrameMac*)impl
2502 {
2503     return m_frame;
2504 }
2505
2506 @end