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