6d2b8a0b0f23a6c5c79868e4406cc3555311756b
[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     return WebCore::TextEncoding(textEncodingName).decode(reinterpret_cast<const char*>([data bytes]), [data length]);
1492 }
1493
1494 - (BOOL)needsLayout
1495 {
1496     RenderObject *renderer = m_frame->renderer();
1497     return renderer ? renderer->needsLayout() : false;
1498 }
1499
1500 - (void)setNeedsLayout
1501 {
1502     RenderObject *renderer = m_frame->renderer();
1503     if (renderer)
1504         renderer->setNeedsLayout(true);
1505 }
1506
1507 - (BOOL)interceptKeyEvent:(NSEvent *)event toView:(NSView *)view
1508 {
1509     return m_frame->keyEvent(event);
1510 }
1511
1512 - (NSString *)renderTreeAsExternalRepresentation
1513 {
1514     return externalRepresentation(m_frame->renderer()).getNSString();
1515 }
1516
1517 - (void)setSelectionFromNone
1518 {
1519     m_frame->setSelectionFromNone();
1520 }
1521
1522 - (void)setIsActive:(BOOL)flag
1523 {
1524     m_frame->setIsActive(flag);
1525 }
1526
1527 - (void)setWindowHasFocus:(BOOL)flag
1528 {
1529     m_frame->setWindowHasFocus(flag);
1530 }
1531
1532 - (void)setShouldCreateRenderers:(BOOL)f
1533 {
1534     _shouldCreateRenderers = f;
1535 }
1536
1537 - (BOOL)shouldCreateRenderers
1538 {
1539     return _shouldCreateRenderers;
1540 }
1541
1542 - (int)numPendingOrLoadingRequests
1543 {
1544     Document *doc = m_frame->document();
1545     
1546     if (doc)
1547         return NumberOfPendingOrLoadingRequests (doc->docLoader());
1548     return 0;
1549 }
1550
1551 - (BOOL)doneProcessingData
1552 {
1553     Document *doc = m_frame->document();
1554     if (doc) {
1555         Tokenizer* tok = doc->tokenizer();
1556         if (tok)
1557             return !tok->processingData();
1558     }
1559     return YES;
1560 }
1561
1562 - (BOOL)shouldClose
1563 {
1564     return m_frame->shouldClose();
1565 }
1566
1567 - (NSColor *)bodyBackgroundColor
1568 {
1569     return m_frame->bodyBackgroundColor();
1570 }
1571
1572 // FIXME: Not sure what this method is for.  It seems to only be used by plug-ins over in WebKit.
1573 - (NSColor *)selectionColor
1574 {
1575     return m_frame->isActive() ? [NSColor selectedTextBackgroundColor] : [NSColor secondarySelectedControlColor];
1576 }
1577
1578 - (void)adjustViewSize
1579 {
1580     FrameView *view = m_frame->view();
1581     if (view)
1582         view->adjustViewSize();
1583 }
1584
1585 - (id)accessibilityTree
1586 {
1587     AXObjectCache::enableAccessibility();
1588     if (!m_frame || !m_frame->document())
1589         return nil;
1590     RenderView* root = static_cast<RenderView *>(m_frame->document()->renderer());
1591     if (!root)
1592         return nil;
1593     return m_frame->document()->axObjectCache()->get(root);
1594 }
1595
1596 - (void)setBaseBackgroundColor:(NSColor *)backgroundColor
1597 {
1598     if (m_frame && m_frame->view()) {
1599         NSColor *deviceColor = [backgroundColor colorUsingColorSpaceName:NSDeviceRGBColorSpace];
1600         Color color = Color(makeRGBA((int)(255 * [deviceColor redComponent]),
1601                                      (int)(255 * [deviceColor blueComponent]),
1602                                      (int)(255 * [deviceColor greenComponent]),
1603                                      (int)(255 * [deviceColor alphaComponent])));
1604         m_frame->view()->setBaseBackgroundColor(color);
1605     }
1606 }
1607
1608 - (void)setDrawsBackground:(BOOL)drawsBackground
1609 {
1610     if (m_frame && m_frame->view())
1611         m_frame->view()->setTransparent(!drawsBackground);
1612 }
1613
1614 - (void)undoEditing:(id)arg
1615 {
1616     ASSERT([arg isKindOfClass:[WebCoreEditCommand class]]);
1617     [arg command]->unapply();
1618 }
1619
1620 - (void)redoEditing:(id)arg
1621 {
1622     ASSERT([arg isKindOfClass:[WebCoreEditCommand class]]);
1623     [arg command]->reapply();
1624 }
1625
1626 - (DOMRange *)rangeByExpandingSelectionWithGranularity:(WebBridgeSelectionGranularity)granularity
1627 {
1628     if (!m_frame->hasSelection())
1629         return nil;
1630
1631     // NOTE: The enums *must* match the very similar ones declared in SelectionController.h
1632     Selection selection(m_frame->selectionController()->selection());
1633     selection.expandUsingGranularity(static_cast<TextGranularity>(granularity));
1634     return [DOMRange _rangeWith:selection.toRange().get()];
1635 }
1636
1637 - (DOMRange *)rangeByAlteringCurrentSelection:(WebSelectionAlteration)alteration direction:(WebBridgeSelectionDirection)direction granularity:(WebBridgeSelectionGranularity)granularity
1638 {
1639     if (!m_frame->hasSelection())
1640         return nil;
1641
1642     // NOTE: The enums *must* match the very similar ones declared in SelectionController.h
1643     SelectionController selectionController;
1644     selectionController.setSelection(m_frame->selectionController()->selection());
1645     selectionController.modify(static_cast<SelectionController::EAlter>(alteration), 
1646                                static_cast<SelectionController::EDirection>(direction), 
1647                                static_cast<TextGranularity>(granularity));
1648     return [DOMRange _rangeWith:selectionController.toRange().get()];
1649 }
1650
1651 - (void)alterCurrentSelection:(WebSelectionAlteration)alteration direction:(WebBridgeSelectionDirection)direction granularity:(WebBridgeSelectionGranularity)granularity
1652 {
1653     if (!m_frame->hasSelection())
1654         return;
1655
1656     // NOTE: The enums *must* match the very similar ones declared in SelectionController.h
1657     SelectionController* selectionController = m_frame->selectionController();
1658     selectionController->modify(static_cast<SelectionController::EAlter>(alteration), 
1659                                 static_cast<SelectionController::EDirection>(direction), 
1660                                 static_cast<TextGranularity>(granularity), true);
1661 }
1662
1663 - (void)alterCurrentSelection:(WebSelectionAlteration)alteration verticalDistance:(float)verticalDistance
1664 {
1665     if (!m_frame->hasSelection())
1666         return;
1667     SelectionController* selectionController = m_frame->selectionController();
1668     selectionController->modify(static_cast<SelectionController::EAlter>(alteration), static_cast<int>(verticalDistance), true);
1669 }
1670
1671 - (WebBridgeSelectionGranularity)selectionGranularity
1672 {
1673     // NOTE: The enums *must* match the very similar ones declared in SelectionController.h
1674     return static_cast<WebBridgeSelectionGranularity>(m_frame->selectionGranularity());
1675 }
1676
1677 - (void)setSelectedDOMRange:(DOMRange *)range affinity:(NSSelectionAffinity)selectionAffinity closeTyping:(BOOL)closeTyping
1678 {
1679     Node *startContainer = [[range startContainer] _node];
1680     Node *endContainer = [[range endContainer] _node];
1681     ASSERT(startContainer);
1682     ASSERT(endContainer);
1683     ASSERT(startContainer->document() == endContainer->document());
1684     
1685     m_frame->document()->updateLayoutIgnorePendingStylesheets();
1686
1687     EAffinity affinity = static_cast<EAffinity>(selectionAffinity);
1688     
1689     // Non-collapsed ranges are not allowed to start at the end of a line that is wrapped,
1690     // they start at the beginning of the next line instead
1691     if (![range collapsed])
1692         affinity = DOWNSTREAM;
1693     
1694     // FIXME: Can we provide extentAffinity?
1695     VisiblePosition visibleStart(startContainer, [range startOffset], affinity);
1696     VisiblePosition visibleEnd(endContainer, [range endOffset], SEL_DEFAULT_AFFINITY);
1697     Selection selection(visibleStart, visibleEnd);
1698     m_frame->selectionController()->setSelection(selection, closeTyping);
1699 }
1700
1701 - (DOMRange *)selectedDOMRange
1702 {
1703     return [DOMRange _rangeWith:m_frame->selectionController()->toRange().get()];
1704 }
1705
1706 - (NSRange)convertToNSRange:(Range *)range
1707 {
1708     if (!range || range->isDetached()) {
1709         return NSMakeRange(NSNotFound, 0);
1710     }
1711
1712     RefPtr<Range> fromStartRange(m_frame->document()->createRange());
1713     int exception = 0;
1714
1715     fromStartRange->setEnd(range->startContainer(exception), range->startOffset(exception), exception);
1716     int startPosition = TextIterator::rangeLength(fromStartRange.get());
1717
1718     fromStartRange->setEnd(range->endContainer(exception), range->endOffset(exception), exception);
1719     int endPosition = TextIterator::rangeLength(fromStartRange.get());
1720
1721     return NSMakeRange(startPosition, endPosition - startPosition);
1722 }
1723
1724 - (PassRefPtr<Range>)convertToDOMRange:(NSRange)nsrange
1725 {
1726     if (nsrange.location > INT_MAX)
1727         return 0;
1728     if (nsrange.length > INT_MAX || nsrange.location + nsrange.length > INT_MAX)
1729         nsrange.length = INT_MAX - nsrange.location;
1730
1731     return TextIterator::rangeFromLocationAndLength(m_frame->document(), nsrange.location, nsrange.length);
1732 }
1733
1734 - (DOMRange *)convertNSRangeToDOMRange:(NSRange)nsrange
1735 {
1736     return [DOMRange _rangeWith:[self convertToDOMRange:nsrange].get()];
1737 }
1738
1739 - (NSRange)convertDOMRangeToNSRange:(DOMRange *)range
1740 {
1741     return [self convertToNSRange:[range _range]];
1742 }
1743
1744 - (void)selectNSRange:(NSRange)range
1745 {
1746     m_frame->selectionController()->setSelection(Selection([self convertToDOMRange:range].get(), SEL_DEFAULT_AFFINITY));
1747 }
1748
1749 - (NSRange)selectedNSRange
1750 {
1751     return [self convertToNSRange:m_frame->selectionController()->toRange().get()];
1752 }
1753
1754 - (NSSelectionAffinity)selectionAffinity
1755 {
1756     return static_cast<NSSelectionAffinity>(m_frame->selectionController()->affinity());
1757 }
1758
1759 - (void)setMarkDOMRange:(DOMRange *)range
1760 {
1761     Range* r = [range _range];
1762     m_frame->setMark(Selection(startPosition(r), endPosition(r), SEL_DEFAULT_AFFINITY));
1763 }
1764
1765 - (DOMRange *)markDOMRange
1766 {
1767     return [DOMRange _rangeWith:m_frame->mark().toRange().get()];
1768 }
1769
1770 - (void)setMarkedTextDOMRange:(DOMRange *)range customAttributes:(NSArray *)attributes ranges:(NSArray *)ranges
1771 {
1772     m_frame->setMarkedTextRange([range _range], attributes, ranges);
1773 }
1774
1775 - (DOMRange *)markedTextDOMRange
1776 {
1777     return [DOMRange _rangeWith:m_frame->markedTextRange()];
1778 }
1779
1780 - (NSRange)markedTextNSRange
1781 {
1782     return [self convertToNSRange:m_frame->markedTextRange()];
1783 }
1784
1785 - (void)replaceMarkedTextWithText:(NSString *)text
1786 {
1787     if (!m_frame->hasSelection())
1788         return;
1789     
1790     int exception = 0;
1791
1792     Range *markedTextRange = m_frame->markedTextRange();
1793     if (markedTextRange && !markedTextRange->collapsed(exception))
1794         TypingCommand::deleteKeyPressed(m_frame->document(), NO);
1795     
1796     if ([text length] > 0)
1797         TypingCommand::insertText(m_frame->document(), text, YES);
1798     
1799     m_frame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded);
1800 }
1801
1802 - (BOOL)canDeleteRange:(DOMRange *)range
1803 {
1804     Node *startContainer = [[range startContainer] _node];
1805     Node *endContainer = [[range endContainer] _node];
1806     if (startContainer == nil || endContainer == nil)
1807         return NO;
1808     
1809     if (!startContainer->isContentEditable() || !endContainer->isContentEditable())
1810         return NO;
1811     
1812     if ([range collapsed]) {
1813         VisiblePosition start(startContainer, [range startOffset], DOWNSTREAM);
1814         VisiblePosition previous = start.previous();
1815         // FIXME: We sometimes allow deletions at the start of editable roots, like when the caret is in an empty list item.
1816         if (previous.isNull() || previous.deepEquivalent().node()->rootEditableElement() != startContainer->rootEditableElement())
1817             return NO;
1818     }
1819     
1820     return YES;
1821 }
1822
1823 // Given proposedRange, returns an extended range that includes adjacent whitespace that should
1824 // be deleted along with the proposed range in order to preserve proper spacing and punctuation of
1825 // the text surrounding the deletion.
1826 - (DOMRange *)smartDeleteRangeForProposedRange:(DOMRange *)proposedRange
1827 {
1828     Node *startContainer = [[proposedRange startContainer] _node];
1829     Node *endContainer = [[proposedRange endContainer] _node];
1830     if (startContainer == nil || endContainer == nil)
1831         return nil;
1832
1833     ASSERT(startContainer->document() == endContainer->document());
1834     
1835     m_frame->document()->updateLayoutIgnorePendingStylesheets();
1836
1837     Position start(startContainer, [proposedRange startOffset]);
1838     Position end(endContainer, [proposedRange endOffset]);
1839     Position newStart = start.upstream().leadingWhitespacePosition(DOWNSTREAM, true);
1840     if (newStart.isNull())
1841         newStart = start;
1842     Position newEnd = end.downstream().trailingWhitespacePosition(DOWNSTREAM, true);
1843     if (newEnd.isNull())
1844         newEnd = end;
1845
1846     RefPtr<Range> range = m_frame->document()->createRange();
1847     int exception = 0;
1848     range->setStart(newStart.node(), newStart.offset(), exception);
1849     range->setEnd(newStart.node(), newStart.offset(), exception);
1850     return [DOMRange _rangeWith:range.get()];
1851 }
1852
1853 // Determines whether whitespace needs to be added around aString to preserve proper spacing and
1854 // punctuation when itÕs inserted into the receiverÕs text over charRange. Returns by reference
1855 // in beforeString and afterString any whitespace that should be added, unless either or both are
1856 // nil. Both are returned as nil if aString is nil or if smart insertion and deletion are disabled.
1857 - (void)smartInsertForString:(NSString *)pasteString replacingRange:(DOMRange *)rangeToReplace beforeString:(NSString **)beforeString afterString:(NSString **)afterString
1858 {
1859     // give back nil pointers in case of early returns
1860     if (beforeString)
1861         *beforeString = nil;
1862     if (afterString)
1863         *afterString = nil;
1864         
1865     // inspect destination
1866     Node *startContainer = [[rangeToReplace startContainer] _node];
1867     Node *endContainer = [[rangeToReplace endContainer] _node];
1868
1869     Position startPos(startContainer, [rangeToReplace startOffset]);
1870     Position endPos(endContainer, [rangeToReplace endOffset]);
1871
1872     VisiblePosition startVisiblePos = VisiblePosition(startPos, VP_DEFAULT_AFFINITY);
1873     VisiblePosition endVisiblePos = VisiblePosition(endPos, VP_DEFAULT_AFFINITY);
1874     
1875     // this check also ensures startContainer, startPos, endContainer, and endPos are non-null
1876     if (startVisiblePos.isNull() || endVisiblePos.isNull())
1877         return;
1878
1879     bool addLeadingSpace = startPos.leadingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isStartOfParagraph(startVisiblePos);
1880     if (addLeadingSpace)
1881         if (UChar previousChar = startVisiblePos.previous().characterAfter())
1882             addLeadingSpace = !m_frame->isCharacterSmartReplaceExempt(previousChar, true);
1883     
1884     bool addTrailingSpace = endPos.trailingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isEndOfParagraph(endVisiblePos);
1885     if (addTrailingSpace)
1886         if (UChar thisChar = endVisiblePos.characterAfter())
1887             addTrailingSpace = !m_frame->isCharacterSmartReplaceExempt(thisChar, false);
1888     
1889     // inspect source
1890     bool hasWhitespaceAtStart = false;
1891     bool hasWhitespaceAtEnd = false;
1892     unsigned pasteLength = [pasteString length];
1893     if (pasteLength > 0) {
1894         NSCharacterSet *whiteSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
1895         
1896         if ([whiteSet characterIsMember:[pasteString characterAtIndex:0]]) {
1897             hasWhitespaceAtStart = YES;
1898         }
1899         if ([whiteSet characterIsMember:[pasteString characterAtIndex:(pasteLength - 1)]]) {
1900             hasWhitespaceAtEnd = YES;
1901         }
1902     }
1903     
1904     // issue the verdict
1905     if (beforeString && addLeadingSpace && !hasWhitespaceAtStart)
1906         *beforeString = @" ";
1907     if (afterString && addTrailingSpace && !hasWhitespaceAtEnd)
1908         *afterString = @" ";
1909 }
1910
1911 - (DOMDocumentFragment *)documentFragmentWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString 
1912 {
1913     if (!m_frame || !m_frame->document())
1914         return 0;
1915
1916     return [DOMDocumentFragment _documentFragmentWith:createFragmentFromMarkup(m_frame->document(), markupString, baseURLString).get()];
1917 }
1918
1919 - (DOMDocumentFragment *)documentFragmentWithText:(NSString *)text inContext:(DOMRange *)context
1920 {
1921     return [DOMDocumentFragment _documentFragmentWith:createFragmentFromText([context _range], text).get()];
1922 }
1923
1924 - (DOMDocumentFragment *)documentFragmentWithNodesAsParagraphs:(NSArray *)nodes
1925 {
1926     if (!m_frame || !m_frame->document())
1927         return 0;
1928     
1929     NSEnumerator *nodeEnum = [nodes objectEnumerator];
1930     Vector<Node*> nodesVector;
1931     DOMNode *node;
1932     while ((node = [nodeEnum nextObject]))
1933         nodesVector.append([node _node]);
1934     
1935     return [DOMDocumentFragment _documentFragmentWith:createFragmentFromNodes(m_frame->document(), nodesVector).get()];
1936 }
1937
1938 - (void)replaceSelectionWithFragment:(DOMDocumentFragment *)fragment selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle
1939 {
1940     if (!m_frame->hasSelection() || !fragment)
1941         return;
1942     
1943     applyCommand(new ReplaceSelectionCommand(m_frame->document(), [fragment _documentFragment], selectReplacement, smartReplace, matchStyle));
1944     m_frame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded);
1945 }
1946
1947 - (void)replaceSelectionWithNode:(DOMNode *)node selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle
1948 {
1949     DOMDocumentFragment *fragment = [[self DOMDocument] createDocumentFragment];
1950     [fragment appendChild:node];
1951     [self replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:matchStyle];
1952 }
1953
1954 - (void)replaceSelectionWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1955 {
1956     DOMDocumentFragment *fragment = [self documentFragmentWithMarkupString:markupString baseURLString:baseURLString];
1957     [self replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:NO];
1958 }
1959
1960 - (void)replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1961 {
1962     [self replaceSelectionWithFragment:[self documentFragmentWithText:text
1963         inContext:[DOMRange _rangeWith:m_frame->selectionController()->toRange().get()]]
1964         selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:YES];
1965 }
1966
1967 - (bool)canIncreaseSelectionListLevel
1968 {
1969     return IncreaseSelectionListLevelCommand::canIncreaseSelectionListLevel(m_frame->document());
1970 }
1971
1972 - (bool)canDecreaseSelectionListLevel
1973 {
1974     return DecreaseSelectionListLevelCommand::canDecreaseSelectionListLevel(m_frame->document());
1975 }
1976
1977 - (DOMNode *)increaseSelectionListLevel;
1978 {
1979     if (!m_frame->hasSelection())
1980         return nil;
1981     
1982     Node* newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevel(m_frame->document());
1983     m_frame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded);
1984     return [DOMNode _nodeWith:newList];
1985 }
1986
1987 - (DOMNode *)increaseSelectionListLevelOrdered;
1988 {
1989     if (!m_frame->hasSelection())
1990         return nil;
1991     
1992     Node* newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevelOrdered(m_frame->document());
1993     m_frame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded);
1994     return [DOMNode _nodeWith:newList];
1995 }
1996
1997 - (DOMNode *)increaseSelectionListLevelUnordered;
1998 {
1999     if (!m_frame->hasSelection())
2000         return nil;
2001     
2002     Node* newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevelUnordered(m_frame->document());
2003     m_frame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded);
2004     return [DOMNode _nodeWith:newList];
2005 }
2006
2007 - (void)decreaseSelectionListLevel
2008 {
2009     if (!m_frame->hasSelection())
2010         return;
2011     
2012     DecreaseSelectionListLevelCommand::decreaseSelectionListLevel(m_frame->document());
2013     m_frame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded);
2014 }
2015
2016 - (void)insertLineBreak
2017 {
2018     if (!m_frame->hasSelection())
2019         return;
2020     
2021     TypingCommand::insertLineBreak(m_frame->document());
2022     m_frame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded);
2023 }
2024
2025 - (void)insertParagraphSeparator
2026 {
2027     if (!m_frame->hasSelection())
2028         return;
2029     
2030     TypingCommand::insertParagraphSeparator(m_frame->document());
2031     m_frame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded);
2032 }
2033
2034 - (void)insertParagraphSeparatorInQuotedContent
2035 {
2036     if (!m_frame->hasSelection())
2037         return;
2038     
2039     TypingCommand::insertParagraphSeparatorInQuotedContent(m_frame->document());
2040     m_frame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded);
2041 }
2042
2043 - (void)insertText:(NSString *)text selectInsertedText:(BOOL)selectInsertedText
2044 {
2045     if (!m_frame->hasSelection())
2046         return;
2047     
2048     TypingCommand::insertText(m_frame->document(), text, selectInsertedText);
2049     m_frame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded);
2050 }
2051
2052 - (void)setSelectionToDragCaret
2053 {
2054     m_frame->selectionController()->setSelection(m_frame->dragCaretController()->selection());
2055 }
2056
2057 - (void)moveSelectionToDragCaret:(DOMDocumentFragment *)selectionFragment smartMove:(BOOL)smartMove
2058 {
2059     applyCommand(new MoveSelectionCommand([selectionFragment _documentFragment], m_frame->dragCaretController()->base(), smartMove));
2060 }
2061
2062 - (VisiblePosition)_visiblePositionForPoint:(NSPoint)point
2063 {
2064     IntPoint outerPoint(point);
2065     Node* node = m_frame->nodeInfoAtPoint(outerPoint, true).innerNode();
2066     if (!node)
2067         return VisiblePosition();
2068     RenderObject* renderer = node->renderer();
2069     if (!renderer)
2070         return VisiblePosition();
2071     FrameView* outerView = m_frame->view();
2072     FrameView* innerView = node->document()->view();
2073     IntPoint innerPoint = innerView->viewportToContents(outerView->contentsToViewport(outerPoint));
2074     return renderer->positionForCoordinates(innerPoint.x(), innerPoint.y());
2075 }
2076
2077 - (void)moveDragCaretToPoint:(NSPoint)point
2078 {   
2079     Selection dragCaret([self _visiblePositionForPoint:point]);
2080     m_frame->dragCaretController()->setSelection(dragCaret);
2081 }
2082
2083 - (void)removeDragCaret
2084 {
2085     m_frame->dragCaretController()->clear();
2086 }
2087
2088 - (DOMRange *)dragCaretDOMRange
2089 {
2090     return [DOMRange _rangeWith:m_frame->dragCaretController()->toRange().get()];
2091 }
2092
2093 - (BOOL)isDragCaretRichlyEditable
2094 {
2095     return m_frame->dragCaretController()->isContentRichlyEditable();
2096 }
2097
2098 - (DOMRange *)editableDOMRangeForPoint:(NSPoint)point
2099 {
2100     VisiblePosition position = [self _visiblePositionForPoint:point];
2101     return position.isNull() ? nil : [DOMRange _rangeWith:Selection(position).toRange().get()];
2102 }
2103
2104 - (DOMRange *)characterRangeAtPoint:(NSPoint)point
2105 {
2106     VisiblePosition position = [self _visiblePositionForPoint:point];
2107     if (position.isNull())
2108         return nil;
2109     
2110     VisiblePosition previous = position.previous();
2111     if (previous.isNotNull()) {
2112         DOMRange *previousCharacterRange = [DOMRange _rangeWith:makeRange(previous, position).get()];
2113         NSRect rect = [self firstRectForDOMRange:previousCharacterRange];
2114         if (NSPointInRect(point, rect))
2115             return previousCharacterRange;
2116     }
2117
2118     VisiblePosition next = position.next();
2119     if (next.isNotNull()) {
2120         DOMRange *nextCharacterRange = [DOMRange _rangeWith:makeRange(position, next).get()];
2121         NSRect rect = [self firstRectForDOMRange:nextCharacterRange];
2122         if (NSPointInRect(point, rect))
2123             return nextCharacterRange;
2124     }
2125     
2126     return nil;
2127 }
2128
2129 - (void)deleteSelectionWithSmartDelete:(BOOL)smartDelete
2130 {
2131     if (!m_frame->hasSelection())
2132         return;
2133     
2134     applyCommand(new DeleteSelectionCommand(m_frame->document(), smartDelete));
2135 }
2136
2137 - (void)deleteKeyPressedWithSmartDelete:(BOOL)smartDelete granularity:(WebBridgeSelectionGranularity)granularity
2138 {
2139     if (!m_frame || !m_frame->document())
2140         return;
2141     
2142     TypingCommand::deleteKeyPressed(m_frame->document(), smartDelete, static_cast<TextGranularity>(granularity));
2143     m_frame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded);
2144 }
2145
2146 - (void)forwardDeleteKeyPressedWithSmartDelete:(BOOL)smartDelete granularity:(WebBridgeSelectionGranularity)granularity
2147 {
2148     if (!m_frame || !m_frame->document())
2149         return;
2150     
2151     TypingCommand::forwardDeleteKeyPressed(m_frame->document(), smartDelete, static_cast<TextGranularity>(granularity));
2152     m_frame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded);
2153 }
2154
2155 - (DOMCSSStyleDeclaration *)typingStyle
2156 {
2157     if (!m_frame || !m_frame->typingStyle())
2158         return nil;
2159     return [DOMCSSStyleDeclaration _CSSStyleDeclarationWith:m_frame->typingStyle()->copy().get()];
2160 }
2161
2162 - (void)setTypingStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(WebUndoAction)undoAction
2163 {
2164     if (!m_frame)
2165         return;
2166     m_frame->computeAndSetTypingStyle([style _CSSStyleDeclaration], static_cast<EditAction>(undoAction));
2167 }
2168
2169 - (void)applyStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(WebUndoAction)undoAction
2170 {
2171     if (!m_frame)
2172         return;
2173     m_frame->applyStyle([style _CSSStyleDeclaration], static_cast<EditAction>(undoAction));
2174 }
2175
2176 - (void)applyParagraphStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(WebUndoAction)undoAction
2177 {
2178     if (!m_frame)
2179         return;
2180     m_frame->applyParagraphStyle([style _CSSStyleDeclaration], static_cast<EditAction>(undoAction));
2181 }
2182
2183 - (BOOL)selectionStartHasStyle:(DOMCSSStyleDeclaration *)style
2184 {
2185     if (!m_frame)
2186         return NO;
2187     return m_frame->selectionStartHasStyle([style _CSSStyleDeclaration]);
2188 }
2189
2190 - (NSCellStateValue)selectionHasStyle:(DOMCSSStyleDeclaration *)style
2191 {
2192     if (!m_frame)
2193         return NSOffState;
2194     switch (m_frame->selectionHasStyle([style _CSSStyleDeclaration])) {
2195         case Frame::falseTriState:
2196             return NSOffState;
2197         case Frame::trueTriState:
2198             return NSOnState;
2199         case Frame::mixedTriState:
2200             return NSMixedState;
2201     }
2202     return NSOffState;
2203 }
2204
2205 - (void)applyEditingStyleToBodyElement
2206 {
2207     if (!m_frame)
2208         return;
2209     m_frame->applyEditingStyleToBodyElement();
2210 }
2211
2212 - (void)removeEditingStyleFromBodyElement
2213 {
2214     if (!m_frame)
2215         return;
2216     m_frame->removeEditingStyleFromBodyElement();
2217 }
2218
2219 - (void)applyEditingStyleToElement:(DOMElement *)element
2220 {
2221     if (!m_frame)
2222         return;
2223     m_frame->applyEditingStyleToElement([element _element]);
2224 }
2225
2226 - (void)removeEditingStyleFromElement:(DOMElement *)element
2227 {
2228     if (!m_frame)
2229         return;
2230     m_frame->removeEditingStyleFromElement([element _element]);
2231 }
2232
2233 - (NSFont *)fontForSelection:(BOOL *)hasMultipleFonts
2234 {
2235     bool multipleFonts = false;
2236     NSFont *font = nil;
2237     if (m_frame)
2238         font = m_frame->fontForSelection(hasMultipleFonts ? &multipleFonts : 0);
2239     if (hasMultipleFonts)
2240         *hasMultipleFonts = multipleFonts;
2241     return font;
2242 }
2243
2244 - (NSDictionary *)fontAttributesForSelectionStart
2245 {
2246     return m_frame ? m_frame->fontAttributesForSelectionStart() : nil;
2247 }
2248
2249 - (NSWritingDirection)baseWritingDirectionForSelectionStart
2250 {
2251     // FIXME: remove this NSWritingDirection cast once <rdar://problem/4509035> is fixed
2252     return m_frame ? m_frame->baseWritingDirectionForSelectionStart() : (NSWritingDirection)NSWritingDirectionLeftToRight;
2253 }
2254
2255 - (BOOL)eventMayStartDrag:(NSEvent *)event
2256 {
2257     return m_frame ? m_frame->eventMayStartDrag(event) : NO;
2258 }
2259
2260 static IntPoint globalPoint(NSWindow* window, NSPoint windowPoint)
2261 {
2262     return IntPoint(flipScreenPoint([window convertBaseToScreen:windowPoint]));
2263 }
2264
2265 static PlatformMouseEvent createMouseEventFromDraggingInfo(NSWindow* window, id <NSDraggingInfo> info)
2266 {
2267     // FIXME: Fake modifier keys here.
2268     // [info draggingLocation] is in window coords
2269     return PlatformMouseEvent(IntPoint([info draggingLocation]), globalPoint(window, [info draggingLocation]),
2270         LeftButton, 0, false, false, false, false);
2271 }
2272
2273 - (NSDragOperation)dragOperationForDraggingInfo:(id <NSDraggingInfo>)info
2274 {
2275     NSDragOperation op = NSDragOperationNone;
2276     if (m_frame) {
2277         RefPtr<FrameView> v = m_frame->view();
2278         if (v) {
2279             ClipboardMac::AccessPolicy policy = m_frame->baseURL().isLocalFile() ? ClipboardMac::Readable : ClipboardMac::TypesReadable;
2280             RefPtr<ClipboardMac> clipboard = new ClipboardMac(true, [info draggingPasteboard], policy);
2281             NSDragOperation srcOp = [info draggingSourceOperationMask];
2282             clipboard->setSourceOperation(srcOp);
2283
2284             PlatformMouseEvent event = createMouseEventFromDraggingInfo([self window], info);
2285             if (v->updateDragAndDrop(event, clipboard.get())) {
2286                 // *op unchanged if no source op was set
2287                 if (!clipboard->destinationOperation(&op)) {
2288                     // The element accepted but they didn't pick an operation, so we pick one for them
2289                     // (as does WinIE).
2290                     if (srcOp & NSDragOperationCopy) {
2291                         op = NSDragOperationCopy;
2292                     } else if (srcOp & NSDragOperationMove || srcOp & NSDragOperationGeneric) {
2293                         op = NSDragOperationMove;
2294                     } else if (srcOp & NSDragOperationLink) {
2295                         op = NSDragOperationLink;
2296                     } else {
2297                         op = NSDragOperationGeneric;
2298                     }
2299                 } else if (!(op & srcOp)) {
2300                     // make sure WC picked an op that was offered.  Cocoa doesn't seem to enforce this,
2301                     // but IE does.
2302                     op = NSDragOperationNone;
2303                 }
2304             }
2305             clipboard->setAccessPolicy(ClipboardMac::Numb);    // invalidate clipboard here for security
2306             return op;
2307         }
2308     }
2309     return op;
2310 }
2311
2312 - (void)dragExitedWithDraggingInfo:(id <NSDraggingInfo>)info
2313 {
2314     if (m_frame) {
2315         RefPtr<FrameView> v = m_frame->view();
2316         if (v) {
2317             // Sending an event can result in the destruction of the view and part.
2318             ClipboardMac::AccessPolicy policy = m_frame->baseURL().isLocalFile() ? ClipboardMac::Readable : ClipboardMac::TypesReadable;
2319             RefPtr<ClipboardMac> clipboard = new ClipboardMac(true, [info draggingPasteboard], policy);
2320             clipboard->setSourceOperation([info draggingSourceOperationMask]);            
2321             v->cancelDragAndDrop(createMouseEventFromDraggingInfo([self window], info), clipboard.get());
2322             clipboard->setAccessPolicy(ClipboardMac::Numb);    // invalidate clipboard here for security
2323         }
2324     }
2325 }
2326
2327 - (BOOL)concludeDragForDraggingInfo:(id <NSDraggingInfo>)info
2328 {
2329     if (m_frame) {
2330         RefPtr<FrameView> v = m_frame->view();
2331         if (v) {
2332             // Sending an event can result in the destruction of the view and part.
2333             RefPtr<ClipboardMac> clipboard = new ClipboardMac(true, [info draggingPasteboard], ClipboardMac::Readable);
2334             clipboard->setSourceOperation([info draggingSourceOperationMask]);
2335             BOOL result = v->performDragAndDrop(createMouseEventFromDraggingInfo([self window], info), clipboard.get());
2336             clipboard->setAccessPolicy(ClipboardMac::Numb);    // invalidate clipboard here for security
2337             return result;
2338         }
2339     }
2340     return NO;
2341 }
2342
2343 - (void)dragSourceMovedTo:(NSPoint)windowLoc
2344 {
2345     if (m_frame) {
2346         // FIXME: Fake modifier keys here.
2347         PlatformMouseEvent event(IntPoint(windowLoc), globalPoint([self window], windowLoc),
2348             LeftButton, 0, false, false, false, false);
2349         m_frame->dragSourceMovedTo(event);
2350     }
2351 }
2352
2353 - (void)dragSourceEndedAt:(NSPoint)windowLoc operation:(NSDragOperation)operation
2354 {
2355     if (m_frame) {
2356         // FIXME: Fake modifier keys here.
2357         PlatformMouseEvent event(IntPoint(windowLoc), globalPoint([self window], windowLoc),
2358             LeftButton, 0, false, false, false, false);
2359         m_frame->dragSourceEndedAt(event, operation);
2360     }
2361 }
2362
2363 - (BOOL)mayDHTMLCut
2364 {
2365     return m_frame->mayDHTMLCut();
2366 }
2367
2368 - (BOOL)mayDHTMLCopy
2369 {
2370     return m_frame->mayDHTMLCopy();
2371 }
2372
2373 - (BOOL)mayDHTMLPaste
2374 {
2375     return m_frame->mayDHTMLPaste();
2376 }
2377
2378 - (BOOL)tryDHTMLCut
2379 {
2380     return m_frame->tryDHTMLCut();
2381 }
2382
2383 - (BOOL)tryDHTMLCopy
2384 {
2385     return m_frame->tryDHTMLCopy();
2386 }
2387
2388 - (BOOL)tryDHTMLPaste
2389 {
2390     return m_frame->tryDHTMLPaste();
2391 }
2392
2393 - (DOMRange *)rangeOfCharactersAroundCaret
2394 {
2395     if (!m_frame)
2396         return nil;
2397         
2398     Selection selection(m_frame->selectionController()->selection());
2399     if (!selection.isCaret())
2400         return nil;
2401
2402     VisiblePosition caret(selection.visibleStart());
2403     VisiblePosition next = caret.next();
2404     VisiblePosition previous = caret.previous();
2405     if (previous.isNull() || next.isNull() || caret == next || caret == previous)
2406         return nil;
2407
2408     return [DOMRange _rangeWith:makeRange(previous, next).get()];
2409 }
2410
2411 - (NSMutableDictionary *)dashboardRegions
2412 {
2413     return m_frame->dashboardRegionsDictionary();
2414 }
2415
2416 // FIXME: The following 2 functions are copied from AppKit. It would be best share code.
2417
2418 // MF:!!! For now we will use static character sets for the computation, but we should eventually probably make these keys in the language dictionaries.
2419 // 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).
2420 // 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).
2421 // MF:!!! Another difference in both of these sets from the old text object is we include all the whitespace in whitespaceAndNewlineCharacterSet.
2422 #define _preSmartString @"([\"\'#$/-`{"
2423 #define _postSmartString @")].,;:?\'!\"%*-/}"
2424
2425 static NSCharacterSet *_getPreSmartSet(void)
2426 {
2427     static NSMutableCharacterSet *_preSmartSet = nil;
2428     if (!_preSmartSet) {
2429         _preSmartSet = [[NSMutableCharacterSet characterSetWithCharactersInString:_preSmartString] retain];
2430         [_preSmartSet formUnionWithCharacterSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
2431         // Adding CJK ranges
2432         [_preSmartSet addCharactersInRange:NSMakeRange(0x1100, 256)]; // Hangul Jamo (0x1100 - 0x11FF)
2433         [_preSmartSet addCharactersInRange:NSMakeRange(0x2E80, 352)]; // CJK & Kangxi Radicals (0x2E80 - 0x2FDF)
2434         [_preSmartSet addCharactersInRange:NSMakeRange(0x2FF0, 464)]; // Ideograph Descriptions, CJK Symbols, Hiragana, Katakana, Bopomofo, Hangul Compatibility Jamo, Kanbun, & Bopomofo Ext (0x2FF0 - 0x31BF)
2435         [_preSmartSet addCharactersInRange:NSMakeRange(0x3200, 29392)]; // Enclosed CJK, CJK Ideographs (Uni Han & Ext A), & Yi (0x3200 - 0xA4CF)
2436         [_preSmartSet addCharactersInRange:NSMakeRange(0xAC00, 11183)]; // Hangul Syllables (0xAC00 - 0xD7AF)
2437         [_preSmartSet addCharactersInRange:NSMakeRange(0xF900, 352)]; // CJK Compatibility Ideographs (0xF900 - 0xFA5F)
2438         [_preSmartSet addCharactersInRange:NSMakeRange(0xFE30, 32)]; // CJK Compatibility From (0xFE30 - 0xFE4F)
2439         [_preSmartSet addCharactersInRange:NSMakeRange(0xFF00, 240)]; // Half/Full Width Form (0xFF00 - 0xFFEF)
2440         [_preSmartSet addCharactersInRange:NSMakeRange(0x20000, 0xA6D7)]; // CJK Ideograph Exntension B
2441         [_preSmartSet addCharactersInRange:NSMakeRange(0x2F800, 0x021E)]; // CJK Compatibility Ideographs (0x2F800 - 0x2FA1D)
2442     }
2443     return _preSmartSet;
2444 }
2445
2446 static NSCharacterSet *_getPostSmartSet(void)
2447 {
2448     static NSMutableCharacterSet *_postSmartSet = nil;
2449     if (!_postSmartSet) {
2450         _postSmartSet = [[NSMutableCharacterSet characterSetWithCharactersInString:_postSmartString] retain];
2451         [_postSmartSet formUnionWithCharacterSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
2452         [_postSmartSet addCharactersInRange:NSMakeRange(0x1100, 256)]; // Hangul Jamo (0x1100 - 0x11FF)
2453         [_postSmartSet addCharactersInRange:NSMakeRange(0x2E80, 352)]; // CJK & Kangxi Radicals (0x2E80 - 0x2FDF)
2454         [_postSmartSet addCharactersInRange:NSMakeRange(0x2FF0, 464)]; // Ideograph Descriptions, CJK Symbols, Hiragana, Katakana, Bopomofo, Hangul Compatibility Jamo, Kanbun, & Bopomofo Ext (0x2FF0 - 0x31BF)
2455         [_postSmartSet addCharactersInRange:NSMakeRange(0x3200, 29392)]; // Enclosed CJK, CJK Ideographs (Uni Han & Ext A), & Yi (0x3200 - 0xA4CF)
2456         [_postSmartSet addCharactersInRange:NSMakeRange(0xAC00, 11183)]; // Hangul Syllables (0xAC00 - 0xD7AF)
2457         [_postSmartSet addCharactersInRange:NSMakeRange(0xF900, 352)]; // CJK Compatibility Ideographs (0xF900 - 0xFA5F)
2458         [_postSmartSet addCharactersInRange:NSMakeRange(0xFE30, 32)]; // CJK Compatibility From (0xFE30 - 0xFE4F)
2459         [_postSmartSet addCharactersInRange:NSMakeRange(0xFF00, 240)]; // Half/Full Width Form (0xFF00 - 0xFFEF)
2460         [_postSmartSet addCharactersInRange:NSMakeRange(0x20000, 0xA6D7)]; // CJK Ideograph Exntension B
2461         [_postSmartSet addCharactersInRange:NSMakeRange(0x2F800, 0x021E)]; // CJK Compatibility Ideographs (0x2F800 - 0x2FA1D)        
2462         [_postSmartSet formUnionWithCharacterSet:[NSCharacterSet punctuationCharacterSet]];
2463     }
2464     return _postSmartSet;
2465 }
2466
2467 - (BOOL)isCharacterSmartReplaceExempt:(unichar)c isPreviousCharacter:(BOOL)isPreviousCharacter
2468 {
2469     return [isPreviousCharacter ? _getPreSmartSet() : _getPostSmartSet() characterIsMember:c];
2470 }
2471
2472 - (BOOL)getData:(NSData **)data andResponse:(NSURLResponse **)response forURL:(NSURL *)URL
2473 {
2474     Document* doc = [self impl]->document();
2475     if (!doc)
2476         return NO;
2477
2478     CachedResource* o = doc->docLoader()->cachedObject([URL absoluteString]);
2479     if (!o)
2480         return NO;
2481
2482     *data = o->allData();
2483     *response = o->response();
2484     return YES;
2485 }
2486
2487 - (void)getAllResourceDatas:(NSArray **)datas andResponses:(NSArray **)responses
2488 {
2489     Document* doc = [self impl]->document();
2490     if (!doc) {
2491         NSArray* emptyArray = [NSArray array];
2492         *datas = emptyArray;
2493         *responses = emptyArray;
2494         return;
2495     }
2496
2497     const HashMap<String, CachedResource*>& allResources = doc->docLoader()->allCachedObjects();
2498
2499     NSMutableArray *d = [[NSMutableArray alloc] initWithCapacity:allResources.size()];
2500     NSMutableArray *r = [[NSMutableArray alloc] initWithCapacity:allResources.size()];
2501
2502     HashMap<String, CachedResource*>::const_iterator end = allResources.end();
2503     for (HashMap<String, CachedResource*>::const_iterator it = allResources.begin(); it != end; ++it) {
2504         [d addObject:it->second->allData()];
2505         [r addObject:it->second->response()];
2506     }
2507
2508     *datas = [d autorelease];
2509     *responses = [r autorelease];
2510 }
2511
2512 - (BOOL)canProvideDocumentSource
2513 {
2514     String mimeType = m_frame->resourceRequest().m_responseMIMEType;
2515     
2516     if (WebCore::DOMImplementation::isTextMIMEType(mimeType) ||
2517         Image::supportsType(mimeType) ||
2518         PlugInInfoStore::supportsMIMEType(mimeType))
2519         return NO;
2520     
2521     return YES;
2522 }
2523
2524 - (BOOL)canSaveAsWebArchive
2525 {
2526     // Currently, all documents that we can view source for
2527     // (HTML and XML documents) can also be saved as web archives
2528     return [self canProvideDocumentSource];
2529 }
2530
2531 - (BOOL)containsPlugins
2532 {
2533     return m_frame->containsPlugins();
2534 }
2535
2536 - (void)setInViewSourceMode:(BOOL)flag
2537 {
2538     m_frame->setInViewSourceMode(flag);
2539 }
2540
2541 - (BOOL)inViewSourceMode
2542 {
2543     return m_frame->inViewSourceMode();
2544 }
2545
2546 - (void)setProhibitsScrolling:(BOOL)prohibits
2547 {
2548     m_frame->setProhibitsScrolling(prohibits);
2549 }
2550
2551 @end
2552
2553 @implementation WebCoreFrameBridge (WebCoreBridgeInternal)
2554
2555 - (RootObject *)executionContextForView:(NSView *)aView
2556 {
2557     FrameMac *frame = [self impl];
2558     RootObject *root = new RootObject(aView);    // The root gets deleted by JavaScriptCore.
2559     root->setRootObjectImp(Window::retrieveWindow(frame));
2560     root->setInterpreter(frame->jScript()->interpreter());
2561     frame->addPluginRootObject(root);
2562     return root;
2563 }
2564
2565 @end
2566
2567 @implementation WebCoreFrameBridge (WebCoreInternalUse)
2568
2569 - (FrameMac*)impl
2570 {
2571     return m_frame;
2572 }
2573
2574 @end