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