df6c0f1796c9092f0fe3a3acd11d46fae3fda317
[WebKit-https.git] / Source / WebCore / bindings / objc / DOM.mm
1 /*
2  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
3  * Copyright (C) 2006 James G. Speth (speth@end.com)
4  * Copyright (C) 2006 Samuel Weinig (sam.weinig@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 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 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 "DOMInternal.h" // import first to make the private/public trick work
30 #import "DOM.h"
31
32 #import "CachedImage.h"
33 #import "DOMElementInternal.h"
34 #import "DOMHTMLCanvasElement.h"
35 #import "DOMHTMLTableCellElementInternal.h"
36 #import "DOMNodeInternal.h"
37 #import "DOMPrivate.h"
38 #import "DOMRangeInternal.h"
39 #import "DragImage.h"
40 #import "Font.h"
41 #import "Frame.h"
42 #import "HTMLElement.h"
43 #import "HTMLNames.h"
44 #import "HTMLParserIdioms.h"
45 #import "HTMLTableCellElement.h"
46 #import "Image.h"
47 #import "JSNode.h"
48 #import "NodeFilter.h"
49 #import "Range.h"
50 #import "RenderImage.h"
51 #import "ScriptController.h"
52 #import "WebScriptObjectPrivate.h"
53 #import <JavaScriptCore/APICast.h>
54 #import <wtf/HashMap.h>
55
56 #if PLATFORM(IOS)
57 #import "FocusController.h"
58 #import "HTMLLinkElement.h"
59 #import "KeyboardEvent.h"
60 #import "URL.h"
61 #import "MediaList.h"
62 #import "MediaQueryEvaluator.h"
63 #import "NodeRenderStyle.h"
64 #import "Page.h"
65 #import "RenderView.h"
66 #import "Touch.h"
67 #import "WAKAppKitStubs.h"
68 #import "WAKWindow.h"
69 #import "WebCoreThreadMessage.h"
70 #endif
71
72 using namespace JSC;
73 using namespace WebCore;
74
75 // FIXME: Would be nice to break this up into separate files to match how other WebKit
76 // code is organized.
77
78 //------------------------------------------------------------------------------------------
79 // DOMNode
80
81 namespace WebCore {
82
83 typedef HashMap<const QualifiedName::QualifiedNameImpl*, Class> ObjCClassMap;
84 static ObjCClassMap* elementClassMap;
85
86 static void addElementClass(const QualifiedName& tag, Class objCClass)
87 {
88     elementClassMap->set(tag.impl(), objCClass);
89 }
90
91 static void createElementClassMap()
92 {
93     // Create the table.
94     elementClassMap = new ObjCClassMap;
95
96     // FIXME: Reflect marquee once the API has been determined.
97
98     // Populate it with HTML and SVG element classes.
99     addElementClass(HTMLNames::aTag, [DOMHTMLAnchorElement class]);
100     addElementClass(HTMLNames::appletTag, [DOMHTMLAppletElement class]);
101     addElementClass(HTMLNames::areaTag, [DOMHTMLAreaElement class]);
102     addElementClass(HTMLNames::baseTag, [DOMHTMLBaseElement class]);
103     addElementClass(HTMLNames::basefontTag, [DOMHTMLBaseFontElement class]);
104     addElementClass(HTMLNames::bodyTag, [DOMHTMLBodyElement class]);
105     addElementClass(HTMLNames::brTag, [DOMHTMLBRElement class]);
106     addElementClass(HTMLNames::buttonTag, [DOMHTMLButtonElement class]);
107     addElementClass(HTMLNames::canvasTag, [DOMHTMLCanvasElement class]);
108     addElementClass(HTMLNames::captionTag, [DOMHTMLTableCaptionElement class]);
109     addElementClass(HTMLNames::colTag, [DOMHTMLTableColElement class]);
110     addElementClass(HTMLNames::colgroupTag, [DOMHTMLTableColElement class]);
111     addElementClass(HTMLNames::delTag, [DOMHTMLModElement class]);
112     addElementClass(HTMLNames::dirTag, [DOMHTMLDirectoryElement class]);
113     addElementClass(HTMLNames::divTag, [DOMHTMLDivElement class]);
114     addElementClass(HTMLNames::dlTag, [DOMHTMLDListElement class]);
115     addElementClass(HTMLNames::embedTag, [DOMHTMLEmbedElement class]);
116     addElementClass(HTMLNames::fieldsetTag, [DOMHTMLFieldSetElement class]);
117     addElementClass(HTMLNames::fontTag, [DOMHTMLFontElement class]);
118     addElementClass(HTMLNames::formTag, [DOMHTMLFormElement class]);
119     addElementClass(HTMLNames::frameTag, [DOMHTMLFrameElement class]);
120     addElementClass(HTMLNames::framesetTag, [DOMHTMLFrameSetElement class]);
121     addElementClass(HTMLNames::h1Tag, [DOMHTMLHeadingElement class]);
122     addElementClass(HTMLNames::h2Tag, [DOMHTMLHeadingElement class]);
123     addElementClass(HTMLNames::h3Tag, [DOMHTMLHeadingElement class]);
124     addElementClass(HTMLNames::h4Tag, [DOMHTMLHeadingElement class]);
125     addElementClass(HTMLNames::h5Tag, [DOMHTMLHeadingElement class]);
126     addElementClass(HTMLNames::h6Tag, [DOMHTMLHeadingElement class]);
127     addElementClass(HTMLNames::headTag, [DOMHTMLHeadElement class]);
128     addElementClass(HTMLNames::hrTag, [DOMHTMLHRElement class]);
129     addElementClass(HTMLNames::htmlTag, [DOMHTMLHtmlElement class]);
130     addElementClass(HTMLNames::iframeTag, [DOMHTMLIFrameElement class]);
131     addElementClass(HTMLNames::imgTag, [DOMHTMLImageElement class]);
132     addElementClass(HTMLNames::inputTag, [DOMHTMLInputElement class]);
133     addElementClass(HTMLNames::insTag, [DOMHTMLModElement class]);
134     addElementClass(HTMLNames::labelTag, [DOMHTMLLabelElement class]);
135     addElementClass(HTMLNames::legendTag, [DOMHTMLLegendElement class]);
136     addElementClass(HTMLNames::liTag, [DOMHTMLLIElement class]);
137     addElementClass(HTMLNames::linkTag, [DOMHTMLLinkElement class]);
138     addElementClass(HTMLNames::listingTag, [DOMHTMLPreElement class]);
139     addElementClass(HTMLNames::mapTag, [DOMHTMLMapElement class]);
140     addElementClass(HTMLNames::marqueeTag, [DOMHTMLMarqueeElement class]);
141     addElementClass(HTMLNames::menuTag, [DOMHTMLMenuElement class]);
142     addElementClass(HTMLNames::metaTag, [DOMHTMLMetaElement class]);
143     addElementClass(HTMLNames::objectTag, [DOMHTMLObjectElement class]);
144     addElementClass(HTMLNames::olTag, [DOMHTMLOListElement class]);
145     addElementClass(HTMLNames::optgroupTag, [DOMHTMLOptGroupElement class]);
146     addElementClass(HTMLNames::optionTag, [DOMHTMLOptionElement class]);
147     addElementClass(HTMLNames::pTag, [DOMHTMLParagraphElement class]);
148     addElementClass(HTMLNames::paramTag, [DOMHTMLParamElement class]);
149     addElementClass(HTMLNames::preTag, [DOMHTMLPreElement class]);
150     addElementClass(HTMLNames::qTag, [DOMHTMLQuoteElement class]);
151     addElementClass(HTMLNames::scriptTag, [DOMHTMLScriptElement class]);
152     addElementClass(HTMLNames::selectTag, [DOMHTMLSelectElement class]);
153     addElementClass(HTMLNames::styleTag, [DOMHTMLStyleElement class]);
154     addElementClass(HTMLNames::tableTag, [DOMHTMLTableElement class]);
155     addElementClass(HTMLNames::tbodyTag, [DOMHTMLTableSectionElement class]);
156     addElementClass(HTMLNames::tdTag, [DOMHTMLTableCellElement class]);
157     addElementClass(HTMLNames::textareaTag, [DOMHTMLTextAreaElement class]);
158     addElementClass(HTMLNames::tfootTag, [DOMHTMLTableSectionElement class]);
159     addElementClass(HTMLNames::thTag, [DOMHTMLTableCellElement class]);
160     addElementClass(HTMLNames::theadTag, [DOMHTMLTableSectionElement class]);
161     addElementClass(HTMLNames::titleTag, [DOMHTMLTitleElement class]);
162     addElementClass(HTMLNames::trTag, [DOMHTMLTableRowElement class]);
163     addElementClass(HTMLNames::ulTag, [DOMHTMLUListElement class]);
164     addElementClass(HTMLNames::xmpTag, [DOMHTMLPreElement class]);
165 }
166
167 static Class lookupElementClass(const QualifiedName& tag)
168 {
169     // Do a special lookup to ignore element prefixes
170     if (tag.hasPrefix())
171         return elementClassMap->get(QualifiedName(nullAtom, tag.localName(), tag.namespaceURI()).impl());
172     
173     return elementClassMap->get(tag.impl());
174 }
175
176 static Class elementClass(const QualifiedName& tag, Class defaultClass)
177 {
178     if (!elementClassMap)
179         createElementClassMap();
180     Class objcClass = lookupElementClass(tag);
181     if (!objcClass)
182         objcClass = defaultClass;
183     return objcClass;
184 }
185
186 static NSArray *kit(const Vector<IntRect>& rects)
187 {
188     size_t size = rects.size();
189     NSMutableArray *array = [NSMutableArray arrayWithCapacity:size];
190     for (size_t i = 0; i < size; ++i)
191         [array addObject:[NSValue valueWithRect:rects[i]]];
192     return array;
193 }
194
195 #if PLATFORM(IOS)
196 static WKQuad wkQuadFromFloatQuad(const FloatQuad& inQuad)
197 {
198     WKQuad  theQuad;
199     theQuad.p1 = inQuad.p1();
200     theQuad.p2 = inQuad.p2();
201     theQuad.p3 = inQuad.p3();
202     theQuad.p4 = inQuad.p4();
203     
204     return theQuad;
205 }
206
207 static NSArray *kit(const Vector<FloatQuad>& quads)
208 {
209     size_t size = quads.size();
210     NSMutableArray *array = [NSMutableArray arrayWithCapacity:size];
211     for (size_t i = 0; i < size; ++i) {
212         WKQuadObject* quadObject = [[WKQuadObject alloc] initWithQuad:wkQuadFromFloatQuad(quads[i])];
213         [array addObject:quadObject];
214         [quadObject release];
215     }
216     return array;
217 }
218
219 static inline float min4(float a, float b, float c, float d)
220 {
221     return std::min(std::min(a, b), std::min(c, d));
222 }
223
224 static inline float max4(float a, float b, float c, float d)
225 {
226     return std::max(std::max(a, b), std::max(c, d));
227 }
228
229 static inline WKQuad emptyQuad()
230 {
231     WKQuad zeroQuad = { CGPointZero, CGPointZero, CGPointZero, CGPointZero };
232     return zeroQuad;
233 }
234 #endif
235
236 } // namespace WebCore
237
238 #if PLATFORM(IOS)
239 @implementation WKQuadObject
240
241 - (id)initWithQuad:(WKQuad)quad
242 {
243     if ((self = [super init]))
244     {
245         _quad = quad;
246     }
247     return self;
248 }
249
250 - (WKQuad)quad
251 {
252     return _quad;
253 }
254
255 - (CGRect)boundingBox
256 {
257     float left      = WebCore::min4(_quad.p1.x, _quad.p2.x, _quad.p3.x, _quad.p4.x);
258     float top       = WebCore::min4(_quad.p1.y, _quad.p2.y, _quad.p3.y, _quad.p4.y);
259     
260     float right     = WebCore::max4(_quad.p1.x, _quad.p2.x, _quad.p3.x, _quad.p4.x);
261     float bottom    = WebCore::max4(_quad.p1.y, _quad.p2.y, _quad.p3.y, _quad.p4.y);
262     
263     return CGRectMake(left, top, right - left, bottom - top);
264 }
265
266 @end
267 #endif
268
269 @implementation DOMNode (WebCoreInternal)
270
271 #pragma clang diagnostic push
272 #pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
273
274 - (NSString *)description
275 {
276     if (!_internal)
277         return [NSString stringWithFormat:@"<%@: null>", [[self class] description]];
278
279     NSString *value = [self nodeValue];
280     if (value)
281         return [NSString stringWithFormat:@"<%@ [%@]: %p '%@'>",
282             [[self class] description], [self nodeName], _internal, value];
283
284     return [NSString stringWithFormat:@"<%@ [%@]: %p>", [[self class] description], [self nodeName], _internal];
285 }
286
287 #pragma clang diagnostic pop
288
289 - (JSC::Bindings::RootObject*)_rootObject
290 {
291     WebCore::Frame* frame = core(self)->document().frame();
292     if (!frame)
293         return 0;
294     return frame->script().bindingRootObject();
295 }
296
297 @end
298
299 Class kitClass(WebCore::Node* impl)
300 {
301     switch (impl->nodeType()) {
302         case WebCore::Node::ELEMENT_NODE:
303             if (impl->isHTMLElement())
304                 return WebCore::elementClass(toHTMLElement(impl)->tagQName(), [DOMHTMLElement class]);
305             return [DOMElement class];
306         case WebCore::Node::ATTRIBUTE_NODE:
307             return [DOMAttr class];
308         case WebCore::Node::TEXT_NODE:
309             return [DOMText class];
310         case WebCore::Node::CDATA_SECTION_NODE:
311             return [DOMCDATASection class];
312         case WebCore::Node::ENTITY_REFERENCE_NODE:
313             return [DOMEntityReference class];
314         case WebCore::Node::ENTITY_NODE:
315             return [DOMEntity class];
316         case WebCore::Node::PROCESSING_INSTRUCTION_NODE:
317             return [DOMProcessingInstruction class];
318         case WebCore::Node::COMMENT_NODE:
319             return [DOMComment class];
320         case WebCore::Node::DOCUMENT_NODE:
321             if (static_cast<WebCore::Document*>(impl)->isHTMLDocument())
322                 return [DOMHTMLDocument class];
323             return [DOMDocument class];
324         case WebCore::Node::DOCUMENT_TYPE_NODE:
325             return [DOMDocumentType class];
326         case WebCore::Node::DOCUMENT_FRAGMENT_NODE:
327             return [DOMDocumentFragment class];
328         case WebCore::Node::NOTATION_NODE:
329             return [DOMNotation class];
330         case WebCore::Node::XPATH_NAMESPACE_NODE:
331             // FIXME: Create an XPath objective C wrapper
332             // See http://bugs.webkit.org/show_bug.cgi?id=8755
333             return nil;
334     }
335     ASSERT_NOT_REACHED();
336     return nil;
337 }
338
339 id <DOMEventTarget> kit(WebCore::EventTarget* eventTarget)
340 {
341     if (!eventTarget)
342         return nil;
343
344     if (WebCore::Node* node = eventTarget->toNode())
345         return kit(node);
346
347     // We don't have an ObjC binding for XMLHttpRequest.
348
349     return nil;
350 }
351
352 @implementation DOMNode (DOMNodeExtensions)
353
354 #if PLATFORM(IOS)
355 - (CGRect)boundingBox
356 #else
357 - (NSRect)boundingBox
358 #endif
359 {
360     // FIXME: Could we move this function to WebCore::Node and autogenerate?
361     core(self)->document().updateLayoutIgnorePendingStylesheets();
362     WebCore::RenderObject* renderer = core(self)->renderer();
363     if (!renderer)
364 #if PLATFORM(IOS)
365         return CGRectZero;
366 #else
367         return NSZeroRect;
368 #endif
369     return renderer->absoluteBoundingBoxRect();
370 }
371
372 - (NSArray *)lineBoxRects
373 {
374     return [self textRects];
375 }
376
377 #if PLATFORM(IOS)
378 // quad in page coordinates, taking transforms into account. c.f. - (NSRect)boundingBox;
379 - (WKQuad)absoluteQuad
380 {
381     return [self absoluteQuadAndInsideFixedPosition:0];
382 }
383
384 - (WKQuad)absoluteQuadAndInsideFixedPosition:(BOOL *)insideFixed
385 {
386     core(self)->document().updateLayoutIgnorePendingStylesheets();
387     WebCore::RenderObject *renderer = core(self)->renderer();
388     if (renderer) {
389         Vector<FloatQuad> quads;
390         bool wasFixed = false;
391         renderer->absoluteQuads(quads, &wasFixed);
392         if (insideFixed)
393             *insideFixed = wasFixed;
394
395         if (quads.size() == 0)
396             return WebCore::emptyQuad();
397         
398         if (quads.size() == 1)
399             return wkQuadFromFloatQuad(quads[0]);
400
401         FloatRect boundingRect = quads[0].boundingBox();
402         for (size_t i = 1; i < quads.size(); ++i)
403             boundingRect.unite(quads[i].boundingBox());
404
405         return wkQuadFromFloatQuad(boundingRect);
406     }
407
408     return WebCore::emptyQuad();
409 }
410
411 // this method is like - (CGRect)boundingBox, but it accounts for for transforms
412 - (CGRect)boundingBoxUsingTransforms
413 {
414     core(self)->document().updateLayoutIgnorePendingStylesheets();
415     WebCore::RenderObject* renderer = core(self)->renderer();
416     if (!renderer)
417         return CGRectZero;
418     return renderer->absoluteBoundingBoxRect(true);
419 }
420
421 // returns array of WKQuadObject
422 - (NSArray *)lineBoxQuads
423 {
424     core(self)->document().updateLayoutIgnorePendingStylesheets();
425     WebCore::RenderObject *renderer = core(self)->renderer();
426     if (renderer) {
427         Vector<WebCore::FloatQuad> quads;
428         renderer->absoluteQuads(quads);
429         return kit(quads);
430     }
431     return nil;
432 }
433
434 - (Element *)_linkElement
435 {
436     WebCore::Node* node = core(self);
437     
438     while (node) {
439         if (node->isLink())
440             return static_cast<WebCore::Element*>(node);
441         node = node->parentNode();
442     }
443     
444     return 0;
445 }
446
447 - (NSURL *)hrefURL
448 {
449     Element *link= [self _linkElement];
450     if (link)
451         return link->document().completeURL(stripLeadingAndTrailingHTMLSpaces(link->getAttribute(HTMLNames::hrefAttr)));
452     
453     return nil;
454 }
455
456 - (NSString *)hrefTarget
457 {
458     Element *target = [self _linkElement];
459     
460     if(target) return target->getAttribute(HTMLNames::targetAttr);
461     
462     return nil;
463 }
464
465 - (CGRect)hrefFrame
466 {
467     RenderObject *renderer = [self _linkElement]->renderer();
468     if (renderer)
469         return renderer->absoluteBoundingBoxRect();
470     return CGRectZero;
471 }
472
473 - (NSString *)hrefLabel
474 {
475     Element *link= [self _linkElement];
476     
477     if (!link) return nil;
478     
479     return link->textContent();
480 }
481
482 - (NSString *)hrefTitle
483 {
484     Element *link= [self _linkElement];
485     
486     if (!link) return nil;
487     
488     return link->document().displayStringModifiedByEncoding(static_cast<HTMLElement *>(link)->title());
489 }
490
491 - (CGRect)boundingFrame
492 {
493     return [self boundingBox];
494 }
495
496 - (WKQuad)innerFrameQuad       // takes transforms into account
497 {
498     core(self)->document().updateLayoutIgnorePendingStylesheets();
499     RenderObject* renderer = core(self)->renderer();
500     if (!renderer)
501         return emptyQuad();
502
503     RenderStyle& style = renderer->style();
504     IntRect boundingBox = renderer->absoluteBoundingBoxRect(true /* use transforms*/);
505
506     boundingBox.move(style.borderLeftWidth(), style.borderTopWidth());
507     boundingBox.setWidth(boundingBox.width() - style.borderLeftWidth() - style.borderRightWidth());
508     boundingBox.setHeight(boundingBox.height() - style.borderBottomWidth() - style.borderTopWidth());
509
510     // FIXME: This function advertises returning a quad, but it actually returns a bounding box (so there is no rotation, for instance).
511     return wkQuadFromFloatQuad(FloatQuad(boundingBox));
512 }
513
514 - (float)computedFontSize
515 {
516     WebCore::Node *node = core(self);
517     RenderStyle *style = node->renderStyle();
518     if (!style)
519         return 0.0f;
520     return style->fontDescription().computedSize();
521 }
522
523 - (DOMNode *)nextFocusNode
524 {
525     Page *page = core(self)->document().page();
526     if (!page)
527         return nil;
528
529     RefPtr<KeyboardEvent> key = KeyboardEvent::create();
530     return kit(page->focusController().nextFocusableElement(FocusNavigationScope::focusNavigationScopeOf(&core(self)->document()), core(self), key.get()));
531 }
532
533 - (DOMNode *)previousFocusNode
534 {
535     Page *page = core(self)->document().page();
536     if (!page)
537         return nil;
538
539     RefPtr<KeyboardEvent> key = KeyboardEvent::create();
540     return kit(page->focusController().previousFocusableElement(FocusNavigationScope::focusNavigationScopeOf(&core(self)->document()), core(self), key.get()));
541 }
542
543 #endif // PLATFORM(IOS)
544
545 @end
546
547 @implementation DOMNode (DOMNodeExtensionsPendingPublic)
548
549 #if !PLATFORM(IOS)
550 - (NSImage *)renderedImage
551 {
552     // FIXME: Could we move this function to WebCore::Node and autogenerate?
553     WebCore::Node* node = core(self);
554     WebCore::Frame* frame = node->document().frame();
555     if (!frame)
556         return nil;
557     return createDragImageForNode(*frame, *node).autorelease();
558 }
559 #endif
560
561 - (NSArray *)textRects
562 {
563     core(self)->document().updateLayoutIgnorePendingStylesheets();
564     if (!core(self)->renderer())
565         return nil;
566     Vector<WebCore::IntRect> rects;
567     core(self)->textRects(rects);
568     return kit(rects);
569 }
570
571 @end
572
573 @implementation DOMNode (WebPrivate)
574
575 + (id)_nodeFromJSWrapper:(JSObjectRef)jsWrapper
576 {
577     JSObject* object = toJS(jsWrapper);
578
579     if (!object->inherits(JSNode::info()))
580         return nil;
581
582     WebCore::Node& node = jsCast<JSNode*>(object)->impl();
583     return kit(&node);
584 }
585
586 @end
587
588 @implementation DOMRange (DOMRangeExtensions)
589
590 #if PLATFORM(IOS)
591 - (CGRect)boundingBox
592 #else
593 - (NSRect)boundingBox
594 #endif
595 {
596     // FIXME: The call to updateLayoutIgnorePendingStylesheets should be moved into WebCore::Range.
597     core(self)->ownerDocument().updateLayoutIgnorePendingStylesheets();
598     return core(self)->boundingBox();
599 }
600
601 #if !PLATFORM(IOS)
602 - (NSImage *)renderedImageForcingBlackText:(BOOL)forceBlackText
603 #else
604 - (CGImageRef)renderedImageForcingBlackText:(BOOL)forceBlackText
605 #endif
606 {
607     WebCore::Range* range = core(self);
608     WebCore::Frame* frame = range->ownerDocument().frame();
609     if (!frame)
610         return nil;
611
612     return createDragImageForRange(*frame, *range, forceBlackText).autorelease();
613 }
614
615 - (NSArray *)textRects
616 {
617     // FIXME: The call to updateLayoutIgnorePendingStylesheets should be moved into WebCore::Range.
618     Vector<WebCore::IntRect> rects;
619     core(self)->ownerDocument().updateLayoutIgnorePendingStylesheets();
620     core(self)->textRects(rects);
621     return kit(rects);
622 }
623
624 - (NSArray *)lineBoxRects
625 {
626     // FIXME: Remove this once all clients stop using it and we drop Leopard support.
627     return [self textRects];
628 }
629
630 @end
631
632 //------------------------------------------------------------------------------------------
633 // DOMElement
634
635 @implementation DOMElement (DOMElementAppKitExtensions)
636
637 #if !PLATFORM(IOS)
638 - (NSImage*)image
639 {
640     // FIXME: Could we move this function to WebCore::Node and autogenerate?
641     WebCore::RenderObject* renderer = core(self)->renderer();
642     if (!renderer || !renderer->isRenderImage())
643         return nil;
644     WebCore::CachedImage* cachedImage = toRenderImage(renderer)->cachedImage();
645     if (!cachedImage || cachedImage->errorOccurred())
646         return nil;
647     return cachedImage->imageForRenderer(toRenderImage(renderer))->getNSImage();
648 }
649 #endif
650
651 @end
652
653 @implementation DOMElement (WebPrivate)
654
655 #if !PLATFORM(IOS)
656 - (NSFont *)_font
657 {
658     // FIXME: Could we move this function to WebCore::Element and autogenerate?
659     auto renderer = core(self)->renderer();
660     if (!renderer)
661         return nil;
662     return renderer->style().font().primaryFont()->getNSFont();
663 }
664 #else
665 - (CTFontRef)_font
666 {
667     RenderObject* renderer = core(self)->renderer();
668     if (!renderer)
669         return nil;
670     return renderer->style().font().primaryFont()->getCTFont();
671 }
672 #endif
673
674 #if !PLATFORM(IOS)
675 - (NSData *)_imageTIFFRepresentation
676 {
677     // FIXME: Could we move this function to WebCore::Element and autogenerate?
678     auto renderer = core(self)->renderer();
679     if (!renderer || !renderer->isRenderImage())
680         return nil;
681     WebCore::CachedImage* cachedImage = toRenderImage(renderer)->cachedImage();
682     if (!cachedImage || cachedImage->errorOccurred())
683         return nil;
684     return (NSData *)cachedImage->imageForRenderer(renderer)->getTIFFRepresentation();
685 }
686 #endif
687
688 - (NSURL *)_getURLAttribute:(NSString *)name
689 {
690     // FIXME: Could we move this function to WebCore::Element and autogenerate?
691     ASSERT(name);
692     WebCore::Element* element = core(self);
693     ASSERT(element);
694     return element->document().completeURL(stripLeadingAndTrailingHTMLSpaces(element->getAttribute(name)));
695 }
696
697 - (BOOL)isFocused
698 {
699     // FIXME: Could we move this function to WebCore::Element and autogenerate?
700     WebCore::Element* element = core(self);
701     return element->document().focusedElement() == element;
702 }
703
704 @end
705
706 #if PLATFORM(IOS)
707 @implementation DOMHTMLLinkElement (WebPrivate)
708 - (BOOL)_mediaQueryMatchesForOrientation:(int)orientation
709 {
710     Document& document = static_cast<HTMLLinkElement*>(core(self))->document();
711     FrameView* frameView = document.frame() ? document.frame()->view() : 0;
712     if (!frameView)
713         return false;
714     int layoutWidth = frameView->layoutWidth();
715     int layoutHeight = frameView->layoutHeight();
716     IntSize savedFixedLayoutSize = frameView->fixedLayoutSize();
717     bool savedUseFixedLayout = frameView->useFixedLayout();
718     if ((orientation == WebMediaQueryOrientationPortrait && layoutWidth > layoutHeight) ||
719         (orientation == WebMediaQueryOrientationLandscape && layoutWidth < layoutHeight)) {
720         // temporarily swap the orientation for the evaluation
721         frameView->setFixedLayoutSize(IntSize(layoutHeight, layoutWidth));
722         frameView->setUseFixedLayout(true);
723     }
724         
725     bool result = [self _mediaQueryMatches];
726
727     frameView->setFixedLayoutSize(savedFixedLayoutSize);
728     frameView->setUseFixedLayout(savedUseFixedLayout);
729
730     return result;
731 }
732
733 - (BOOL)_mediaQueryMatches
734 {
735     HTMLLinkElement* link = static_cast<HTMLLinkElement*>(core(self));
736     String media = link->getAttribute(HTMLNames::mediaAttr);
737     if (media.isEmpty())
738         return true;
739     Document& document = link->document();
740
741     RefPtr<MediaQuerySet> mediaQuerySet = MediaQuerySet::createAllowingDescriptionSyntax(media);
742     MediaQueryEvaluator screenEval("screen", document.frame(), document.renderView() ? &document.renderView()->style() : 0);
743
744     return screenEval.eval(mediaQuerySet.get());
745 }
746 @end
747 #endif
748
749 //------------------------------------------------------------------------------------------
750 // DOMRange
751
752 @implementation DOMRange (WebPrivate)
753
754 - (NSString *)description
755 {
756     if (!_internal)
757         return @"<DOMRange: null>";
758     return [NSString stringWithFormat:@"<DOMRange: %@ %d %@ %d>",
759                [self startContainer], [self startOffset], [self endContainer], [self endOffset]];
760 }
761
762 // FIXME: This should be removed as soon as all internal Apple uses of it have been replaced with
763 // calls to the public method - (NSString *)text.
764 - (NSString *)_text
765 {
766     return [self text];
767 }
768
769 @end
770
771 //------------------------------------------------------------------------------------------
772 // DOMRGBColor
773
774 @implementation DOMRGBColor (WebPrivate)
775
776 #if !PLATFORM(IOS)
777 // FIXME: This should be removed as soon as all internal Apple uses of it have been replaced with
778 // calls to the public method - (NSColor *)color.
779 - (NSColor *)_color
780 {
781     return [self color];
782 }
783 #endif
784
785 @end
786
787
788 @implementation DOMHTMLTableCellElement (WebPrivate)
789
790 - (DOMHTMLTableCellElement *)_cellAbove
791 {
792     return kit(core(self)->cellAbove());
793 }
794
795 @end
796
797 //------------------------------------------------------------------------------------------
798 // DOMNodeFilter
799
800 DOMNodeFilter *kit(WebCore::NodeFilter* impl)
801 {
802     if (!impl)
803         return nil;
804     
805     if (DOMNodeFilter *wrapper = getDOMWrapper(impl))
806         return [[wrapper retain] autorelease];
807     
808     DOMNodeFilter *wrapper = [[DOMNodeFilter alloc] _init];
809     wrapper->_internal = reinterpret_cast<DOMObjectInternal*>(impl);
810     impl->ref();
811     addDOMWrapper(wrapper, impl);
812     return [wrapper autorelease];
813 }
814
815 WebCore::NodeFilter* core(DOMNodeFilter *wrapper)
816 {
817     return wrapper ? reinterpret_cast<WebCore::NodeFilter*>(wrapper->_internal) : 0;
818 }
819
820 @implementation DOMNodeFilter
821
822 - (void)dealloc
823 {
824     if (_internal)
825         reinterpret_cast<WebCore::NodeFilter*>(_internal)->deref();
826     [super dealloc];
827 }
828
829 - (void)finalize
830 {
831     if (_internal)
832         reinterpret_cast<WebCore::NodeFilter*>(_internal)->deref();
833     [super finalize];
834 }
835
836 - (short)acceptNode:(DOMNode *)node
837 {
838     return core(self)->acceptNode(core(node));
839 }
840
841 @end