c5880ea4dd852b5c00ddab3c825d6a9f6cf083cf
[WebKit-https.git] / Source / WebKitLegacy / win / DOMCoreClasses.cpp
1 /*
2  * Copyright (C) 2006-2007, 2009, 2014-2015 Apple Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "WebKitDLL.h"
27 #include "DOMCoreClasses.h"
28
29 #include "DOMCSSClasses.h"
30 #include "DOMEventsClasses.h"
31 #include "DOMHTMLClasses.h"
32 #include "WebKitGraphics.h"
33
34 #include <WebCore/Attr.h>
35 #include <WebCore/BString.h>
36 #include <WebCore/COMPtr.h>
37 #include <WebCore/DOMWindow.h>
38 #include <WebCore/Document.h>
39 #include <WebCore/DragImage.h>
40 #include <WebCore/Element.h>
41 #include <WebCore/Event.h>
42 #include <WebCore/Font.h>
43 #include <WebCore/FontCascade.h>
44 #include <WebCore/Frame.h>
45 #include <WebCore/HTMLCollection.h>
46 #include <WebCore/HTMLFormElement.h>
47 #include <WebCore/HTMLInputElement.h>
48 #include <WebCore/HTMLNames.h>
49 #include <WebCore/HTMLOptionElement.h>
50 #include <WebCore/HTMLSelectElement.h>
51 #include <WebCore/HTMLTextAreaElement.h>
52 #include <WebCore/NamedNodeMap.h>
53 #include <WebCore/NodeList.h>
54 #include <WebCore/Range.h>
55 #include <WebCore/RenderElement.h>
56 #include <WebCore/RenderTreeAsText.h>
57 #include <WebCore/ScrollIntoViewOptions.h>
58 #include <WebCore/StyledElement.h>
59
60 #include <initguid.h>
61 // {3B0C0EFF-478B-4b0b-8290-D2321E08E23E}
62 DEFINE_GUID(IID_DOMElement, 0x3b0c0eff, 0x478b, 0x4b0b, 0x82, 0x90, 0xd2, 0x32, 0x1e, 0x8, 0xe2, 0x3e);
63
64 // Our normal style is just to say "using namespace WebCore" rather than having
65 // individual using directives for each type from that namespace. But
66 // "DOMObject" exists both in the WebCore namespace and unnamespaced in this
67 // file, which leads to ambiguities if we say "using namespace WebCore".
68 using namespace WebCore::HTMLNames;
69 using WTF::AtomicString;
70 using WebCore::BString;
71 using WebCore::Element;
72 using WebCore::ExceptionCode;
73 using WebCore::Frame;
74 using WebCore::IntRect;
75 using WTF::String;
76
77 // DOMObject - IUnknown -------------------------------------------------------
78
79 HRESULT DOMObject::QueryInterface(_In_ REFIID riid, _COM_Outptr_ void** ppvObject)
80 {
81     if (!ppvObject)
82         return E_POINTER;
83     *ppvObject = nullptr;
84     if (IsEqualGUID(riid, IID_IDOMObject))
85         *ppvObject = static_cast<IDOMObject*>(this);
86     else
87         return WebScriptObject::QueryInterface(riid, ppvObject);
88
89     AddRef();
90     return S_OK;
91 }
92
93 // DOMNode - IUnknown ---------------------------------------------------------
94
95 HRESULT DOMNode::QueryInterface(_In_ REFIID riid, _COM_Outptr_ void** ppvObject)
96 {
97     if (!ppvObject)
98         return E_POINTER;
99     *ppvObject = nullptr;
100     if (IsEqualGUID(riid, IID_IDOMNode))
101         *ppvObject = static_cast<IDOMNode*>(this);
102     else if (IsEqualGUID(riid, __uuidof(DOMNode)))
103         *ppvObject = static_cast<DOMNode*>(this);
104     else if (IsEqualGUID(riid, __uuidof(IDOMEventTarget)))
105         *ppvObject = static_cast<IDOMEventTarget*>(this);
106     else
107         return DOMObject::QueryInterface(riid, ppvObject);
108
109     AddRef();
110     return S_OK;
111 }
112
113 // DOMNode --------------------------------------------------------------------
114
115 HRESULT DOMNode::nodeName(__deref_opt_out BSTR* result)
116 {
117     if (!result)
118         return E_POINTER;
119     *result = nullptr;
120     if (!m_node)
121         return E_FAIL;
122
123     *result = BString(m_node->nodeName()).release();
124     return S_OK;
125 }
126
127 HRESULT DOMNode::nodeValue(__deref_opt_out BSTR* result)
128 {
129     if (!result)
130         return E_POINTER;
131     *result = nullptr;
132     if (!m_node)
133         return E_FAIL;
134     WTF::String nodeValueStr = m_node->nodeValue();
135     *result = BString(nodeValueStr).release();
136     if (nodeValueStr.length() && !*result)
137         return E_OUTOFMEMORY;
138     return S_OK;
139 }
140
141 HRESULT DOMNode::setNodeValue(_In_ BSTR /*value*/)
142 {
143     ASSERT_NOT_REACHED();
144     return E_NOTIMPL;
145 }
146
147 HRESULT DOMNode::nodeType(_Out_ unsigned short* /*result*/)
148 {
149     ASSERT_NOT_REACHED();
150     return E_NOTIMPL;
151 }
152
153 HRESULT DOMNode::parentNode(_COM_Outptr_opt_ IDOMNode** result)
154 {
155     if (!result)
156         return E_POINTER;
157     *result = nullptr;
158     if (!m_node || !m_node->parentNode())
159         return E_FAIL;
160     *result = DOMNode::createInstance(m_node->parentNode());
161     return *result ? S_OK : E_FAIL;
162 }
163
164 HRESULT DOMNode::childNodes(_COM_Outptr_opt_ IDOMNodeList** result)
165 {
166     if (!result)
167         return E_POINTER;
168     *result = nullptr;
169     if (!m_node)
170         return E_FAIL;
171
172     if (!result)
173         return E_POINTER;
174
175     *result = DOMNodeList::createInstance(m_node->childNodes().get());
176     return *result ? S_OK : E_FAIL;
177 }
178
179 HRESULT DOMNode::firstChild(_COM_Outptr_opt_ IDOMNode** result)
180 {
181     ASSERT_NOT_REACHED();
182     if (!result)
183         return E_POINTER;
184     *result = nullptr;
185     return E_NOTIMPL;
186 }
187
188 HRESULT DOMNode::lastChild(_COM_Outptr_opt_ IDOMNode** result)
189 {
190     ASSERT_NOT_REACHED();
191     if (!result)
192         return E_POINTER;
193     *result = nullptr;
194     return E_NOTIMPL;
195 }
196
197 HRESULT DOMNode::previousSibling(_COM_Outptr_opt_ IDOMNode** result)
198 {
199     ASSERT_NOT_REACHED();
200     if (!result)
201         return E_POINTER;
202     *result = nullptr;
203     return E_NOTIMPL;
204 }
205
206 HRESULT DOMNode::nextSibling(_COM_Outptr_opt_ IDOMNode** result)
207 {
208     if (!result)
209         return E_POINTER;
210     *result = nullptr;
211     if (!m_node)
212         return E_FAIL;
213     *result = DOMNode::createInstance(m_node->nextSibling());
214     return *result ? S_OK : E_FAIL;
215 }
216
217 HRESULT DOMNode::attributes(_COM_Outptr_opt_ IDOMNamedNodeMap** result)
218 {
219     if (!result)
220         return E_POINTER;
221     *result = nullptr;
222     if (!m_node)
223         return E_FAIL;
224     *result = DOMNamedNodeMap::createInstance(m_node->attributes());
225     return *result ? S_OK : E_FAIL;
226 }
227
228 HRESULT DOMNode::ownerDocument(_COM_Outptr_opt_ IDOMDocument** result)
229 {
230     if (!result)
231         return E_POINTER;
232     *result = nullptr;
233     if (!m_node)
234         return E_FAIL;
235     *result = DOMDocument::createInstance(m_node->ownerDocument());
236     return *result ? S_OK : E_FAIL;
237 }
238
239 HRESULT DOMNode::insertBefore(_In_opt_ IDOMNode* newChild, _In_opt_ IDOMNode* refChild, _COM_Outptr_opt_ IDOMNode** result)
240 {
241     if (!result)
242         return E_POINTER;
243
244     *result = nullptr;
245
246     if (!m_node)
247         return E_FAIL;
248
249     COMPtr<DOMNode> newChildNode(Query, newChild);
250     if (!newChildNode)
251         return E_FAIL;
252
253     COMPtr<DOMNode> refChildNode(Query, refChild);
254
255     if (m_node->insertBefore(*newChildNode->node(), refChildNode ? refChildNode->node() : nullptr).hasException())
256         return E_FAIL;
257
258     *result = newChild;
259     (*result)->AddRef();
260     return S_OK;
261 }
262
263 HRESULT DOMNode::replaceChild(_In_opt_ IDOMNode* /*newChild*/, _In_opt_ IDOMNode* /*oldChild*/, _COM_Outptr_opt_ IDOMNode** result)
264 {
265     ASSERT_NOT_REACHED();
266     if (!result)
267         return E_POINTER;
268     *result = nullptr;
269     return E_NOTIMPL;
270 }
271
272 HRESULT DOMNode::removeChild(_In_opt_ IDOMNode* oldChild, _COM_Outptr_opt_ IDOMNode** result)
273 {
274     if (!result)
275         return E_POINTER;
276
277     *result = nullptr;
278
279     if (!m_node)
280         return E_FAIL;
281
282     COMPtr<DOMNode> oldChildNode(Query, oldChild);
283     if (!oldChildNode)
284         return E_FAIL;
285
286     if (m_node->removeChild(*oldChildNode->node()).hasException())
287         return E_FAIL;
288
289     *result = oldChild;
290     (*result)->AddRef();
291     return S_OK;
292 }
293
294 HRESULT DOMNode::appendChild(_In_opt_ IDOMNode* /*oldChild*/, _COM_Outptr_opt_ IDOMNode** result)
295 {
296     ASSERT_NOT_REACHED();
297     if (!result)
298         return E_POINTER;
299     *result = nullptr;
300     return E_NOTIMPL;
301 }
302
303 HRESULT DOMNode::hasChildNodes(_Out_ BOOL* /*result*/)
304 {
305     ASSERT_NOT_REACHED();
306     return E_NOTIMPL;
307 }
308
309 HRESULT DOMNode::cloneNode(BOOL /*deep*/, _COM_Outptr_opt_ IDOMNode** result)
310 {
311     ASSERT_NOT_REACHED();
312     if (!result)
313         return E_POINTER;
314     *result = nullptr;
315     return E_NOTIMPL;
316 }
317
318 HRESULT DOMNode::normalize()
319 {
320     ASSERT_NOT_REACHED();
321     return E_NOTIMPL;
322 }
323
324 HRESULT DOMNode::isSupported(_In_ BSTR /*feature*/, _In_ BSTR /*version*/, _Out_ BOOL* /*result*/)
325 {
326     ASSERT_NOT_REACHED();
327     return E_NOTIMPL;
328 }
329
330 HRESULT DOMNode::namespaceURI(__deref_opt_out BSTR* result)
331 {
332     ASSERT_NOT_REACHED();
333     if (!result)
334         return E_POINTER;
335     *result = nullptr;
336     return E_NOTIMPL;
337 }
338
339 HRESULT DOMNode::prefix(__deref_opt_out BSTR* result)
340 {
341     ASSERT_NOT_REACHED();
342     if (!result)
343         return E_POINTER;
344     *result = nullptr;
345     return E_NOTIMPL;
346 }
347
348 HRESULT DOMNode::setPrefix(_In_ BSTR /*prefix*/)
349 {
350     ASSERT_NOT_REACHED();
351     return E_NOTIMPL;
352 }
353
354 HRESULT DOMNode::localName(__deref_opt_out BSTR* result)
355 {
356     ASSERT_NOT_REACHED();
357     if (!result)
358         return E_POINTER;
359     *result = nullptr;
360     return E_NOTIMPL;
361 }
362
363 HRESULT DOMNode::hasAttributes(_Out_ BOOL* /*result*/)
364 {
365     ASSERT_NOT_REACHED();
366     return E_NOTIMPL;
367 }
368
369 HRESULT DOMNode::isSameNode(_In_opt_ IDOMNode* other, _Out_ BOOL* result)
370 {
371     if (!result) {
372         ASSERT_NOT_REACHED();
373         return E_POINTER;
374     }
375
376     *result = FALSE;
377
378     if (!other)
379         return E_POINTER;
380
381     COMPtr<DOMNode> domOther;
382     HRESULT hr = other->QueryInterface(__uuidof(DOMNode), (void**)&domOther);
383     if (FAILED(hr))
384         return hr;
385
386     *result = m_node->isSameNode(domOther->node()) ? TRUE : FALSE;
387     return S_OK;
388 }
389
390 HRESULT DOMNode::isEqualNode(_In_opt_ IDOMNode* /*other*/, _Out_ BOOL* /*result*/)
391 {
392     ASSERT_NOT_REACHED();
393     return E_NOTIMPL;
394 }
395
396 HRESULT DOMNode::textContent(__deref_opt_out BSTR* result)
397 {
398     if (!result)
399         return E_POINTER;
400
401     *result = BString(m_node->textContent()).release();
402
403     return S_OK;
404 }
405
406 HRESULT DOMNode::setTextContent(_In_ BSTR /*text*/)
407 {
408     ASSERT_NOT_REACHED();
409     return E_NOTIMPL;
410 }
411
412 // DOMNode - IDOMEventTarget --------------------------------------------------
413
414 HRESULT DOMNode::addEventListener(_In_ BSTR type, _In_opt_ IDOMEventListener* listener, BOOL useCapture)
415 {
416     auto webListener = WebEventListener::create(listener);
417     m_node->addEventListener(type, WTFMove(webListener), useCapture);
418
419     return S_OK;
420 }
421
422 HRESULT DOMNode::removeEventListener(_In_ BSTR type, _In_opt_ IDOMEventListener* listener, BOOL useCapture)
423 {
424     if (!listener || !type)
425         return E_POINTER;
426     if (!m_node)
427         return E_FAIL;
428     auto webListener = WebEventListener::create(listener);
429     m_node->removeEventListener(type, webListener, useCapture);
430     return S_OK;
431 }
432
433 HRESULT DOMNode::dispatchEvent(_In_opt_ IDOMEvent* evt, _Out_ BOOL* result)
434 {
435     if (!evt || !result)
436         return E_POINTER;
437     if (!m_node)
438         return E_FAIL;
439
440     COMPtr<DOMEvent> domEvent;
441     HRESULT hr = evt->QueryInterface(IID_DOMEvent, (void**) &domEvent);
442     if (FAILED(hr))
443         return hr;
444
445     if (!domEvent->coreEvent())
446         return E_FAIL;
447
448     auto dispatchResult = m_node->dispatchEventForBindings(*domEvent->coreEvent());
449     if (dispatchResult.hasException())
450         return E_FAIL;
451
452     *result = dispatchResult.releaseReturnValue();
453     return S_OK;
454 }
455
456 // DOMNode - DOMNode ----------------------------------------------------------
457
458 DOMNode::DOMNode(WebCore::Node* n)
459 {
460     if (n)
461         n->ref();
462
463     m_node = n;
464 }
465
466 DOMNode::~DOMNode()
467 {
468     if (m_node)
469         m_node->deref();
470 }
471
472 IDOMNode* DOMNode::createInstance(WebCore::Node* n)
473 {
474     if (!n)
475         return nullptr;
476
477     HRESULT hr = S_OK;
478     IDOMNode* domNode = nullptr;
479     WebCore::Node::NodeType nodeType = n->nodeType();
480
481     switch (nodeType) {
482         case WebCore::Node::ELEMENT_NODE: 
483         {
484             IDOMElement* newElement = DOMElement::createInstance(static_cast<WebCore::Element*>(n));
485             if (newElement) {
486                 hr = newElement->QueryInterface(IID_IDOMNode, (void**)&domNode);
487                 newElement->Release();
488             }
489         }
490         break;
491         case WebCore::Node::DOCUMENT_NODE:
492         {
493             IDOMDocument* newDocument = DOMDocument::createInstance(&n->document());
494             if (newDocument) {
495                 hr = newDocument->QueryInterface(IID_IDOMNode, (void**)&domNode);
496                 newDocument->Release();
497             }
498         }
499         break;
500         default:
501         {
502             DOMNode* newNode = new DOMNode(n);
503             hr = newNode->QueryInterface(IID_IDOMNode, (void**)&domNode);
504         }
505         break;
506     }
507
508     if (FAILED(hr))
509         return nullptr;
510
511     return domNode;
512 }
513
514 // DOMNodeList - IUnknown -----------------------------------------------------
515
516 HRESULT DOMNodeList::QueryInterface(_In_ REFIID riid, _COM_Outptr_ void** ppvObject)
517 {
518     if (!ppvObject)
519         return E_POINTER;
520     *ppvObject = nullptr;
521     if (IsEqualGUID(riid, IID_IDOMNodeList))
522         *ppvObject = static_cast<IDOMNodeList*>(this);
523     else
524         return DOMObject::QueryInterface(riid, ppvObject);
525
526     AddRef();
527     return S_OK;
528 }
529
530 // IDOMNodeList ---------------------------------------------------------------
531
532 HRESULT DOMNodeList::item(UINT index, _COM_Outptr_opt_ IDOMNode** result)
533 {
534     if (!result)
535         return E_POINTER;
536     *result = nullptr;
537     if (!m_nodeList)
538         return E_FAIL;
539
540     WebCore::Node* itemNode = m_nodeList->item(index);
541     if (!itemNode)
542         return E_FAIL;
543
544     *result = DOMNode::createInstance(itemNode);
545     return *result ? S_OK : E_FAIL;
546 }
547
548 HRESULT DOMNodeList::length(_Out_ UINT* result)
549 {
550     if (!result)
551         return E_POINTER;
552     *result = 0;
553     if (!m_nodeList)
554         return E_FAIL;
555     *result = m_nodeList->length();
556     return S_OK;
557 }
558
559 // DOMNodeList - DOMNodeList --------------------------------------------------
560
561 DOMNodeList::DOMNodeList(WebCore::NodeList* l)
562 {
563     if (l)
564         l->ref();
565
566     m_nodeList = l;
567 }
568
569 DOMNodeList::~DOMNodeList()
570 {
571     if (m_nodeList)
572         m_nodeList->deref();
573 }
574
575 IDOMNodeList* DOMNodeList::createInstance(WebCore::NodeList* l)
576 {
577     if (!l)
578         return nullptr;
579
580     IDOMNodeList* domNodeList = nullptr;
581     DOMNodeList* newNodeList = new DOMNodeList(l);
582     if (FAILED(newNodeList->QueryInterface(IID_IDOMNodeList, (void**)&domNodeList)))
583         return nullptr;
584
585     return domNodeList;
586 }
587
588 // DOMDocument - IUnknown -----------------------------------------------------
589
590 HRESULT DOMDocument::QueryInterface(_In_ REFIID riid, _COM_Outptr_ void** ppvObject)
591 {
592     if (!ppvObject)
593         return E_POINTER;
594     *ppvObject = nullptr;
595     if (IsEqualGUID(riid, IID_IDOMDocument))
596         *ppvObject = static_cast<IDOMDocument*>(this);
597     else if (IsEqualGUID(riid, IID_IDOMViewCSS))
598         *ppvObject = static_cast<IDOMViewCSS*>(this);
599     else if (IsEqualGUID(riid, IID_IDOMDocumentEvent))
600         *ppvObject = static_cast<IDOMDocumentEvent*>(this);
601     else
602         return DOMNode::QueryInterface(riid, ppvObject);
603
604     AddRef();
605     return S_OK;
606 }
607
608 // DOMDocument ----------------------------------------------------------------
609
610 HRESULT DOMDocument::doctype(_COM_Outptr_opt_ IDOMDocumentType** result)
611 {
612     ASSERT_NOT_REACHED();
613     if (!result)
614         return E_POINTER;
615     *result = nullptr;
616     return E_NOTIMPL;
617 }
618
619 HRESULT DOMDocument::implementation(_COM_Outptr_opt_ IDOMImplementation** result)
620 {
621     ASSERT_NOT_REACHED();
622     if (!result)
623         return E_POINTER;
624     *result = nullptr;
625     return E_NOTIMPL;
626 }
627
628 HRESULT DOMDocument::documentElement(_COM_Outptr_opt_ IDOMElement** result)
629 {
630     if (!result)
631         return E_POINTER;
632     *result = DOMElement::createInstance(m_document->documentElement());
633     return *result ? S_OK : E_FAIL;
634 }
635
636 HRESULT DOMDocument::createElement(_In_ BSTR tagName, _COM_Outptr_opt_ IDOMElement** result)
637 {
638     if (!result)
639         return E_POINTER;
640     *result = nullptr;
641     if (!m_document)
642         return E_FAIL;
643
644     String tagNameString(tagName);
645     auto createElementResult = m_document->createElementForBindings(tagNameString);
646     if (createElementResult.hasException())
647         return E_FAIL;
648     *result = DOMElement::createInstance(createElementResult.releaseReturnValue().ptr());
649     return S_OK;
650 }
651
652 HRESULT DOMDocument::createDocumentFragment(_COM_Outptr_opt_ IDOMDocumentFragment** result)
653 {
654     ASSERT_NOT_REACHED();
655     if (!result)
656         return E_POINTER;
657     *result = nullptr;
658     return E_NOTIMPL;
659 }
660
661 HRESULT STDMETHODCALLTYPE DOMDocument::createTextNode(_In_ BSTR /*data*/, _COM_Outptr_opt_ IDOMText** result)
662 {
663     ASSERT_NOT_REACHED();
664     if (!result)
665         return E_POINTER;
666     *result = nullptr;
667     return E_NOTIMPL;
668 }
669
670 HRESULT DOMDocument::createComment(_In_ BSTR /*data*/, _COM_Outptr_opt_ IDOMComment** result)
671 {
672     ASSERT_NOT_REACHED();
673     if (!result)
674         return E_POINTER;
675     *result = nullptr;
676     return E_NOTIMPL;
677 }
678
679 HRESULT DOMDocument::createCDATASection(_In_ BSTR /*data*/, _COM_Outptr_opt_ IDOMCDATASection** result)
680 {
681     ASSERT_NOT_REACHED();
682     if (!result)
683         return E_POINTER;
684     *result = nullptr;
685     return E_NOTIMPL;
686 }
687
688 HRESULT DOMDocument::createProcessingInstruction(_In_ BSTR /*target*/, _In_ BSTR /*data*/, _COM_Outptr_opt_ IDOMProcessingInstruction** result)
689 {
690     ASSERT_NOT_REACHED();
691     if (!result)
692         return E_POINTER;
693     *result = nullptr;
694     return E_NOTIMPL;
695 }
696
697 HRESULT DOMDocument::createAttribute(_In_ BSTR /*name*/, _COM_Outptr_opt_ IDOMAttr** result)
698 {
699     ASSERT_NOT_REACHED();
700     if (!result)
701         return E_POINTER;
702     *result = nullptr;
703     return E_NOTIMPL;
704 }
705
706 HRESULT DOMDocument::createEntityReference(_In_ BSTR /*name*/, _COM_Outptr_opt_ IDOMEntityReference** result)
707 {
708     ASSERT_NOT_REACHED();
709     if (!result)
710         return E_POINTER;
711     *result = nullptr;
712     return E_NOTIMPL;
713 }
714
715 HRESULT DOMDocument::getElementsByTagName(_In_ BSTR tagName, _COM_Outptr_opt_ IDOMNodeList** result)
716 {
717     if (!result)
718         return E_POINTER;
719     *result = nullptr;
720     if (!m_document)
721         return E_FAIL;
722
723     String tagNameString(tagName);
724     RefPtr<WebCore::NodeList> elements;
725     if (!tagNameString.isNull())
726         elements = m_document->getElementsByTagName(tagNameString);
727     *result = DOMNodeList::createInstance(elements.get());
728     return *result ? S_OK : E_FAIL;
729 }
730
731 HRESULT DOMDocument::importNode(_In_opt_ IDOMNode* /*importedNode*/, BOOL /*deep*/, _COM_Outptr_opt_ IDOMNode** result)
732 {
733     ASSERT_NOT_REACHED();
734     if (!result)
735         return E_POINTER;
736     *result = nullptr;
737     return E_NOTIMPL;
738 }
739
740 HRESULT DOMDocument::createElementNS(_In_ BSTR /*namespaceURI*/, _In_ BSTR /*qualifiedName*/, _COM_Outptr_opt_ IDOMElement** result)
741 {
742     ASSERT_NOT_REACHED();
743     if (!result)
744         return E_POINTER;
745     *result = nullptr;
746     return E_NOTIMPL;
747 }
748
749 HRESULT DOMDocument::createAttributeNS(_In_ BSTR /*namespaceURI*/, _In_ BSTR /*qualifiedName*/, _COM_Outptr_opt_ IDOMAttr** result)
750 {
751     ASSERT_NOT_REACHED();
752     if (!result)
753         return E_POINTER;
754     *result = nullptr;
755     return E_NOTIMPL;
756 }
757
758 HRESULT DOMDocument::getElementsByTagNameNS(_In_ BSTR namespaceURI, _In_ BSTR localName, _COM_Outptr_opt_ IDOMNodeList** result)
759 {
760     if (!result)
761         return E_POINTER;
762     *result = nullptr;
763     if (!m_document)
764         return E_FAIL;
765
766     String namespaceURIString(namespaceURI);
767     String localNameString(localName);
768     RefPtr<WebCore::NodeList> elements;
769     if (!localNameString.isNull())
770         elements = m_document->getElementsByTagNameNS(namespaceURIString, localNameString);
771     *result = DOMNodeList::createInstance(elements.get());
772     return *result ? S_OK : E_FAIL;
773 }
774
775 HRESULT DOMDocument::getElementById(_In_ BSTR elementId, _COM_Outptr_opt_ IDOMElement** result)
776 {
777     if (!result)
778         return E_POINTER;
779     *result = nullptr;
780     if (!m_document)
781         return E_FAIL;
782
783     String idString(elementId);
784     *result = DOMElement::createInstance(m_document->getElementById(idString));
785     return *result ? S_OK : E_FAIL;
786 }
787
788 // DOMDocument - IDOMViewCSS --------------------------------------------------
789
790 HRESULT DOMDocument::getComputedStyle(_In_opt_ IDOMElement* elt, _In_ BSTR pseudoElt, _COM_Outptr_opt_ IDOMCSSStyleDeclaration** result)
791 {
792     if (!result)
793         return E_POINTER;
794     *result = nullptr;
795     if (!elt)
796         return E_POINTER;
797
798     COMPtr<DOMElement> domEle;
799     HRESULT hr = elt->QueryInterface(IID_DOMElement, (void**)&domEle);
800     if (FAILED(hr))
801         return hr;
802     Element* element = domEle->element();
803     if (!element)
804         return E_FAIL;
805
806     auto* dv = m_document->domWindow();
807     String pseudoEltString(pseudoElt);
808     
809     if (!dv)
810         return E_FAIL;
811     
812     *result = DOMCSSStyleDeclaration::createInstance(dv->getComputedStyle(*element, pseudoEltString.impl()).ptr());
813     return *result ? S_OK : E_FAIL;
814 }
815
816 // DOMDocument - IDOMDocumentEvent --------------------------------------------
817
818 HRESULT DOMDocument::createEvent(_In_ BSTR eventType, _COM_Outptr_opt_ IDOMEvent** result)
819 {
820     if (!result)
821         return E_POINTER;
822     *result = nullptr;
823
824     String eventTypeString(eventType, SysStringLen(eventType));
825     auto createEventResult = m_document->createEvent(eventTypeString);
826     if (createEventResult.hasException())
827         return E_FAIL;
828     *result = DOMEvent::createInstance(createEventResult.releaseReturnValue());
829     return S_OK;
830 }
831
832 // DOMDocument - DOMDocument --------------------------------------------------
833
834 DOMDocument::DOMDocument(WebCore::Document* d)
835     : DOMNode(d)
836     , m_document(d)
837 {
838 }
839
840 DOMDocument::~DOMDocument()
841 {
842 }
843
844 IDOMDocument* DOMDocument::createInstance(WebCore::Document* d)
845 {
846     if (!d)
847         return nullptr;
848
849     HRESULT hr;
850     IDOMDocument* domDocument = nullptr;
851
852     if (d->isHTMLDocument()) {
853         DOMHTMLDocument* newDocument = new DOMHTMLDocument(d);
854         hr = newDocument->QueryInterface(IID_IDOMDocument, (void**)&domDocument);
855     } else {
856         DOMDocument* newDocument = new DOMDocument(d);
857         hr = newDocument->QueryInterface(IID_IDOMDocument, (void**)&domDocument);
858     }
859
860     if (FAILED(hr))
861         return nullptr;
862
863     return domDocument;
864 }
865
866 // DOMWindow - IUnknown ------------------------------------------------------
867
868 HRESULT DOMWindow::QueryInterface(_In_ REFIID riid, _COM_Outptr_ void** ppvObject)
869 {
870     if (!ppvObject)
871         return E_POINTER;
872     *ppvObject = nullptr;
873     if (IsEqualGUID(riid, IID_IDOMWindow))
874         *ppvObject = static_cast<IDOMWindow*>(this);
875     else if (IsEqualGUID(riid, IID_IDOMEventTarget))
876         *ppvObject = static_cast<IDOMEventTarget*>(this);
877     else
878         return DOMObject::QueryInterface(riid, ppvObject);
879
880     AddRef();
881     return S_OK;
882 }
883
884 // DOMWindow - IDOMWindow ------------------------------------------------------
885
886 HRESULT DOMWindow::document(_COM_Outptr_opt_ IDOMDocument** result)
887 {
888     if (!result) {
889         ASSERT_NOT_REACHED();
890         return E_POINTER;
891     }
892
893     *result = DOMDocument::createInstance(m_window->document());
894     return *result ? S_OK : E_FAIL;
895 }
896
897 HRESULT DOMWindow::getComputedStyle(_In_opt_ IDOMElement* element, _In_ BSTR pseudoElement)
898 {
899     ASSERT_NOT_REACHED();
900     return E_NOTIMPL;
901 }
902
903 HRESULT DOMWindow::getMatchedCSSRules(_In_opt_ IDOMElement* element, _In_ BSTR pseudoElement, BOOL authorOnly, _COM_Outptr_opt_ IDOMCSSRuleList** result)
904 {
905     ASSERT_NOT_REACHED();
906     if (!result)
907         return E_POINTER;
908     *result = nullptr;
909     return E_NOTIMPL;
910 }
911
912 HRESULT DOMWindow::devicePixelRatio(_Out_ double* result)
913 {
914     ASSERT_NOT_REACHED();
915     return E_NOTIMPL;
916 }
917
918 // DOMWindow - IDOMEventTarget ------------------------------------------------------
919
920 HRESULT DOMWindow::addEventListener(_In_ BSTR type, _In_opt_ IDOMEventListener* listener, BOOL useCapture)
921 {
922     if (!type || !listener)
923         return E_POINTER;
924     if (!m_window)
925         return E_FAIL;
926     auto webListener = WebEventListener::create(listener);
927     m_window->addEventListener(type, WTFMove(webListener), useCapture);
928     return S_OK;
929 }
930
931 HRESULT DOMWindow::removeEventListener(_In_ BSTR type, _In_opt_ IDOMEventListener* listener, BOOL useCapture)
932 {
933     if (!type || !listener)
934         return E_POINTER;
935     if (!m_window)
936         return E_FAIL;
937     auto webListener = WebEventListener::create(listener);
938     m_window->removeEventListener(type, webListener, useCapture);
939     return S_OK;
940 }
941
942 HRESULT DOMWindow::dispatchEvent(_In_opt_ IDOMEvent* evt, _Out_ BOOL* result)
943 {
944     if (!result || !evt)
945         return E_POINTER;
946     if (!m_window)
947         return E_FAIL;
948
949     COMPtr<DOMEvent> domEvent;
950     HRESULT hr = evt->QueryInterface(IID_DOMEvent, (void**) &domEvent);
951     if (FAILED(hr))
952         return hr;
953
954     if (!domEvent->coreEvent())
955         return E_FAIL;
956
957     auto dispatchResult = m_window->dispatchEventForBindings(*domEvent->coreEvent());
958     if (dispatchResult.hasException())
959         return E_FAIL;
960
961     *result = dispatchResult.releaseReturnValue();
962     return S_OK;
963 }
964
965
966 // DOMWindow - DOMWindow --------------------------------------------------
967
968 DOMWindow::DOMWindow(WebCore::DOMWindow* w)
969     : m_window(w)
970 {
971 }
972
973 DOMWindow::~DOMWindow()
974 {
975 }
976
977 IDOMWindow* DOMWindow::createInstance(WebCore::DOMWindow* w)
978 {
979     if (!w)
980         return nullptr;
981
982     DOMWindow* newWindow = new DOMWindow(w);
983
984     IDOMWindow* domWindow = nullptr;
985     HRESULT hr = newWindow->QueryInterface(IID_IDOMWindow, reinterpret_cast<void**>(&domWindow));
986
987     if (FAILED(hr))
988         return nullptr;
989
990     return domWindow;
991 }
992
993 // DOMElement - IUnknown ------------------------------------------------------
994
995 HRESULT DOMElement::QueryInterface(_In_ REFIID riid, _COM_Outptr_ void** ppvObject)
996 {
997     if (!ppvObject)
998         return E_POINTER;
999     *ppvObject = nullptr;
1000     if (IsEqualGUID(riid, IID_IDOMElement))
1001         *ppvObject = static_cast<IDOMElement*>(this);
1002     else if (IsEqualGUID(riid, IID_DOMElement))
1003         *ppvObject = static_cast<DOMElement*>(this);
1004     else if (IsEqualGUID(riid, IID_IDOMElementPrivate))
1005         *ppvObject = static_cast<IDOMElementPrivate*>(this);
1006     else if (IsEqualGUID(riid, IID_IDOMNodeExtensions))
1007         *ppvObject = static_cast<IDOMNodeExtensions*>(this);
1008     else if (IsEqualGUID(riid, IID_IDOMElementCSSInlineStyle))
1009         *ppvObject = static_cast<IDOMElementCSSInlineStyle*>(this);
1010     else if (IsEqualGUID(riid, IID_IDOMElementExtensions))
1011         *ppvObject = static_cast<IDOMElementExtensions*>(this);
1012     else
1013         return DOMNode::QueryInterface(riid, ppvObject);
1014
1015     AddRef();
1016     return S_OK;
1017 }
1018
1019 // DOMElement - IDOMNodeExtensions---------------------------------------------
1020
1021 HRESULT DOMElement::boundingBox(_Out_ LPRECT rect)
1022 {
1023     if (!rect)
1024         return E_POINTER;
1025
1026     ::SetRectEmpty(rect);
1027
1028     if (!m_element)
1029         return E_FAIL;
1030
1031     WebCore::RenderElement *renderer = m_element->renderer();
1032     if (renderer) {
1033         IntRect boundsIntRect = renderer->absoluteBoundingBoxRect();
1034         rect->left = boundsIntRect.x();
1035         rect->top = boundsIntRect.y();
1036         rect->right = boundsIntRect.x() + boundsIntRect.width();
1037         rect->bottom = boundsIntRect.y() + boundsIntRect.height();
1038     }
1039
1040     return S_OK;
1041 }
1042
1043 HRESULT DOMElement::lineBoxRects(__inout_ecount_full(cRects) RECT* /*rects*/, int cRects)
1044 {
1045     return E_NOTIMPL;
1046 }
1047
1048 // IDOMElement ----------------------------------------------------------------
1049
1050 HRESULT DOMElement::tagName(__deref_opt_out BSTR* result)
1051 {
1052     if (!result)
1053         return E_POINTER;
1054     *result = nullptr;
1055     if (!m_element)
1056         return E_FAIL;
1057
1058     *result = BString(m_element->tagName()).release();
1059     return S_OK;
1060 }
1061     
1062 HRESULT DOMElement::getAttribute(_In_ BSTR name, __deref_opt_out BSTR* result)
1063 {
1064     if (!result)
1065         return E_POINTER;
1066     *result = nullptr;
1067     if (!m_element)
1068         return E_FAIL;
1069     WTF::String nameString(name, SysStringLen(name));
1070     WTF::String& attrValueString = (WTF::String&) m_element->getAttribute(nameString);
1071     *result = BString(attrValueString).release();
1072     if (attrValueString.length() && !*result)
1073         return E_OUTOFMEMORY;
1074     return S_OK;
1075 }
1076     
1077 HRESULT DOMElement::setAttribute(_In_ BSTR name, _In_ BSTR value)
1078 {
1079     if (!m_element)
1080         return E_FAIL;
1081
1082     WTF::String nameString(name, SysStringLen(name));
1083     WTF::String valueString(value, SysStringLen(value));
1084     auto result = m_element->setAttribute(nameString, valueString);
1085     return result.hasException() ? E_FAIL : S_OK;
1086 }
1087     
1088 HRESULT DOMElement::removeAttribute(_In_ BSTR /*name*/)
1089 {
1090     ASSERT_NOT_REACHED();
1091     return E_NOTIMPL;
1092 }
1093     
1094 HRESULT DOMElement::getAttributeNode(_In_ BSTR /*name*/, _COM_Outptr_opt_ IDOMAttr** result)
1095 {
1096     ASSERT_NOT_REACHED();
1097     if (!result)
1098         return E_POINTER;
1099     *result = nullptr;
1100     return E_NOTIMPL;
1101 }
1102     
1103 HRESULT DOMElement::setAttributeNode(_In_opt_ IDOMAttr* /*newAttr*/, _COM_Outptr_opt_ IDOMAttr** result)
1104 {
1105     ASSERT_NOT_REACHED();
1106     if (!result)
1107         return E_POINTER;
1108     *result = nullptr;
1109     return E_NOTIMPL;
1110 }
1111     
1112 HRESULT DOMElement::removeAttributeNode(_In_opt_ IDOMAttr* /*oldAttr*/, _COM_Outptr_opt_ IDOMAttr** result)
1113 {
1114     ASSERT_NOT_REACHED();
1115     if (!result)
1116         return E_POINTER;
1117     *result = nullptr;
1118     return E_NOTIMPL;
1119 }
1120     
1121 HRESULT DOMElement::getElementsByTagName(_In_ BSTR /*name*/, _COM_Outptr_opt_ IDOMNodeList** result)
1122 {
1123     ASSERT_NOT_REACHED();
1124     if (!result)
1125         return E_POINTER;
1126     *result = nullptr;
1127     return E_NOTIMPL;
1128 }
1129     
1130 HRESULT DOMElement::getAttributeNS(_In_ BSTR /*namespaceURI*/, _In_ BSTR /*localName*/, __deref_opt_out BSTR* result)
1131 {
1132     ASSERT_NOT_REACHED();
1133     if (!result)
1134         return E_POINTER;
1135     *result = nullptr;
1136     return E_NOTIMPL;
1137 }
1138     
1139 HRESULT DOMElement::setAttributeNS(_In_ BSTR /*namespaceURI*/, _In_ BSTR /*qualifiedName*/, _In_ BSTR /*value*/)
1140 {
1141     ASSERT_NOT_REACHED();
1142     return E_NOTIMPL;
1143 }
1144     
1145 HRESULT DOMElement::removeAttributeNS(_In_ BSTR /*namespaceURI*/, _In_ BSTR /*localName*/)
1146 {
1147     ASSERT_NOT_REACHED();
1148     return E_NOTIMPL;
1149 }
1150     
1151 HRESULT DOMElement::getAttributeNodeNS(_In_ BSTR /*namespaceURI*/, _In_ BSTR /*localName*/, _COM_Outptr_opt_ IDOMAttr** result)
1152 {
1153     ASSERT_NOT_REACHED();
1154     if (!result)
1155         return E_POINTER;
1156     *result = nullptr;
1157     return E_NOTIMPL;
1158 }
1159     
1160 HRESULT DOMElement::setAttributeNodeNS(_In_opt_ IDOMAttr* /*newAttr*/, _COM_Outptr_opt_ IDOMAttr** result)
1161 {
1162     ASSERT_NOT_REACHED();
1163     if (!result)
1164         return E_POINTER;
1165     *result = nullptr;
1166     return E_NOTIMPL;
1167 }
1168     
1169 HRESULT DOMElement::getElementsByTagNameNS(_In_ BSTR /*namespaceURI*/, _In_ BSTR /*localName*/, _COM_Outptr_opt_ IDOMNodeList** result)
1170 {
1171     ASSERT_NOT_REACHED();
1172     if (!result)
1173         return E_POINTER;
1174     *result = nullptr;
1175     return E_NOTIMPL;
1176 }
1177     
1178 HRESULT DOMElement::hasAttribute(_In_ BSTR /*name*/, _Out_ BOOL* /*result*/)
1179 {
1180     ASSERT_NOT_REACHED();
1181     return E_NOTIMPL;
1182 }
1183     
1184 HRESULT DOMElement::hasAttributeNS(_In_ BSTR /*namespaceURI*/, _In_ BSTR /*localName*/, _Out_ BOOL* /*result*/)
1185 {
1186     ASSERT_NOT_REACHED();
1187     return E_NOTIMPL;
1188 }
1189
1190 HRESULT DOMElement::focus()
1191 {
1192     if (!m_element)
1193         return E_FAIL;
1194     m_element->focus();
1195     return S_OK;
1196 }
1197
1198 HRESULT DOMElement::blur()
1199 {
1200     if (!m_element)
1201         return E_FAIL;
1202     m_element->blur();
1203     return S_OK;
1204 }
1205
1206 // IDOMElementPrivate ---------------------------------------------------------
1207
1208 HRESULT DOMElement::coreElement(__deref_opt_out void **element)
1209 {
1210     if (!m_element)
1211         return E_FAIL;
1212     *element = (void*) m_element;
1213     return S_OK;
1214 }
1215
1216 HRESULT DOMElement::isEqual(_In_opt_ IDOMElement* other, _Out_ BOOL* result)
1217 {
1218     if (!result)
1219         return E_POINTER;
1220
1221     *result = FALSE;
1222
1223     if (!other)
1224         return E_POINTER;
1225
1226     IDOMElementPrivate* otherPriv;
1227     HRESULT hr = other->QueryInterface(IID_IDOMElementPrivate, (void**) &otherPriv);
1228     if (FAILED(hr))
1229         return hr;
1230     
1231     void* otherCoreEle;
1232     hr = otherPriv->coreElement(&otherCoreEle);
1233     otherPriv->Release();
1234     if (FAILED(hr))
1235         return hr;
1236
1237     *result = (otherCoreEle == (void*)m_element) ? TRUE : FALSE;
1238     return S_OK;
1239 }
1240
1241 HRESULT DOMElement::isFocused(_Out_ BOOL* result)
1242 {
1243     if (!result)
1244         return E_POINTER;
1245     *result = FALSE;
1246     if (!m_element)
1247         return E_FAIL;
1248
1249     if (m_element->document().focusedElement() == m_element)
1250         *result = TRUE;
1251     else
1252         *result = FALSE;
1253
1254     return S_OK;
1255 }
1256
1257 HRESULT DOMElement::innerText(__deref_opt_out BSTR* result)
1258 {
1259     if (!result) {
1260         ASSERT_NOT_REACHED();
1261         return E_POINTER;
1262     }
1263
1264     *result = nullptr;
1265
1266     if (!m_element) {
1267         ASSERT_NOT_REACHED();
1268         return E_FAIL;
1269     }
1270
1271     *result = BString(m_element->innerText()).release();
1272     return S_OK;
1273 }
1274
1275 HRESULT DOMElement::font(_Out_ WebFontDescription* webFontDescription)
1276 {
1277     if (!webFontDescription) {
1278         ASSERT_NOT_REACHED();
1279         return E_POINTER;
1280     }
1281
1282     ASSERT(m_element);
1283
1284     WebCore::RenderElement* renderer = m_element->renderer();
1285     if (!renderer)
1286         return E_FAIL;
1287
1288     auto fontDescription = renderer->style().fontCascade().fontDescription();
1289     AtomicString family = fontDescription.firstFamily();
1290
1291     // FIXME: This leaks. Delete this whole function to get rid of the leak.
1292     UChar* familyCharactersBuffer = new UChar[family.length()];
1293     StringView(family.string()).getCharactersWithUpconvert(familyCharactersBuffer);
1294
1295     webFontDescription->family = familyCharactersBuffer;
1296     webFontDescription->familyLength = family.length();
1297     webFontDescription->size = fontDescription.computedSize();
1298     webFontDescription->bold = isFontWeightBold(fontDescription.weight());
1299     webFontDescription->italic = isItalic(fontDescription.italic());
1300
1301     return S_OK;
1302 }
1303
1304 HRESULT DOMElement::renderedImage(__deref_opt_out HBITMAP* image)
1305 {
1306     if (!image) {
1307         ASSERT_NOT_REACHED();
1308         return E_POINTER;
1309     }
1310     *image = nullptr;
1311
1312     ASSERT(m_element);
1313
1314     Frame* frame = m_element->document().frame();
1315     if (!frame)
1316         return E_FAIL;
1317
1318     *image = createDragImageForNode(*frame, *m_element);
1319     if (!*image)
1320         return E_FAIL;
1321
1322     return S_OK;
1323 }
1324
1325 HRESULT DOMElement::markerTextForListItem(__deref_opt_out BSTR* markerText)
1326 {
1327     if (!markerText)
1328         return E_POINTER;
1329
1330     ASSERT(m_element);
1331
1332     *markerText = BString(WebCore::markerTextForListItem(m_element)).release();
1333     return S_OK;
1334 }
1335
1336 HRESULT DOMElement::shadowPseudoId(__deref_opt_out BSTR* result)
1337 {
1338     if (!result)
1339         return E_POINTER;
1340
1341     ASSERT(m_element);
1342
1343     *result = BString(m_element->shadowPseudoId().string()).release();
1344     return S_OK;
1345 }
1346
1347 // IDOMElementCSSInlineStyle --------------------------------------------------
1348
1349 HRESULT DOMElement::style(_COM_Outptr_opt_ IDOMCSSStyleDeclaration** result)
1350 {
1351     if (!result)
1352         return E_POINTER;
1353     *result = nullptr;
1354     if (!is<WebCore::StyledElement>(m_element))
1355         return E_FAIL;
1356
1357     *result = DOMCSSStyleDeclaration::createInstance(&downcast<WebCore::StyledElement>(*m_element).cssomStyle());
1358     return *result ? S_OK : E_FAIL;
1359 }
1360
1361 // IDOMElementExtensions ------------------------------------------------------
1362
1363 HRESULT DOMElement::offsetLeft(_Out_ int* result)
1364 {
1365     if (!result)
1366         return E_POINTER;
1367     *result = 0;
1368     if (!m_element)
1369         return E_FAIL;
1370
1371     *result = m_element->offsetLeft();
1372     return S_OK;
1373 }
1374
1375 HRESULT DOMElement::offsetTop(_Out_ int* result)
1376 {
1377     if (!result)
1378         return E_POINTER;
1379     *result = 0;
1380     if (!m_element)
1381         return E_FAIL;
1382
1383     *result = m_element->offsetTop();
1384     return S_OK;
1385 }
1386
1387 HRESULT DOMElement::offsetWidth(_Out_ int* result)
1388 {
1389     if (!result)
1390         return E_POINTER;
1391     *result = 0;
1392     if (!m_element)
1393         return E_FAIL;
1394
1395     *result = m_element->offsetWidth();
1396     return S_OK;
1397 }
1398
1399 HRESULT DOMElement::offsetHeight(_Out_ int* result)
1400 {
1401     if (!result)
1402         return E_POINTER;
1403     *result = 0;
1404     if (!m_element)
1405         return E_FAIL;
1406
1407     *result = m_element->offsetHeight();
1408     return S_OK;
1409 }
1410
1411 HRESULT DOMElement::offsetParent(_COM_Outptr_opt_ IDOMElement** result)
1412 {
1413     // FIXME
1414     ASSERT_NOT_REACHED();
1415     if (!result)
1416         return E_POINTER;
1417     *result = nullptr;
1418     return E_NOTIMPL;
1419 }
1420
1421 HRESULT DOMElement::clientWidth(_Out_ int* result)
1422 {
1423     if (!result)
1424         return E_POINTER;
1425     *result = 0;
1426     if (!m_element)
1427         return E_FAIL;
1428
1429     *result = m_element->clientWidth();
1430     return S_OK;
1431 }
1432
1433 HRESULT DOMElement::clientHeight(_Out_ int* result)
1434 {
1435     if (!result)
1436         return E_POINTER;
1437     *result = 0;
1438     if (!m_element)
1439         return E_FAIL;
1440
1441     *result = m_element->clientHeight();
1442     return S_OK;
1443 }
1444
1445 HRESULT DOMElement::scrollLeft(_Out_ int* result)
1446 {
1447     if (!result)
1448         return E_POINTER;
1449     *result = 0;
1450     if (!m_element)
1451         return E_FAIL;
1452
1453     *result = m_element->scrollLeft();
1454     return S_OK;
1455 }
1456
1457 HRESULT DOMElement::setScrollLeft(int /*newScrollLeft*/)
1458 {
1459     // FIXME
1460     ASSERT_NOT_REACHED();
1461     return E_NOTIMPL;
1462 }
1463
1464 HRESULT DOMElement::scrollTop(_Out_ int* result)
1465 {
1466     if (!result)
1467         return E_POINTER;
1468     *result = 0;
1469     if (!m_element)
1470         return E_FAIL;
1471
1472     *result = m_element->scrollTop();
1473     return S_OK;
1474 }
1475
1476 HRESULT DOMElement::setScrollTop(int /*newScrollTop*/)
1477 {
1478     // FIXME
1479     ASSERT_NOT_REACHED();
1480     return E_NOTIMPL;
1481 }
1482
1483 HRESULT DOMElement::scrollWidth(_Out_ int* result)
1484 {
1485     if (!result)
1486         return E_POINTER;
1487     *result = 0;
1488     if (!m_element)
1489         return E_FAIL;
1490
1491     *result = m_element->scrollWidth();
1492     return S_OK;
1493 }
1494
1495 HRESULT DOMElement::scrollHeight(_Out_ int* result)
1496 {
1497     if (!result)
1498         return E_POINTER;
1499     *result = 0;
1500     if (!m_element)
1501         return E_FAIL;
1502
1503     *result = m_element->scrollHeight();
1504     return S_OK;
1505 }
1506
1507 HRESULT DOMElement::scrollIntoView(BOOL alignWithTop)
1508 {
1509     if (!m_element)
1510         return E_FAIL;
1511
1512     m_element->scrollIntoView(!!alignWithTop);
1513     return S_OK;
1514 }
1515
1516 HRESULT DOMElement::scrollIntoViewIfNeeded(BOOL centerIfNeeded)
1517 {
1518     if (!m_element)
1519         return E_FAIL;
1520
1521     m_element->scrollIntoViewIfNeeded(!!centerIfNeeded);
1522     return S_OK;
1523 }
1524
1525 // DOMElement -----------------------------------------------------------------
1526
1527 DOMElement::DOMElement(WebCore::Element* e)
1528     : DOMNode(e)
1529     , m_element(e)
1530 {
1531 }
1532
1533 DOMElement::~DOMElement()
1534 {
1535 }
1536
1537 IDOMElement* DOMElement::createInstance(WebCore::Element* e)
1538 {
1539     if (!e)
1540         return nullptr;
1541
1542     HRESULT hr;
1543     IDOMElement* domElement = nullptr;
1544
1545     if (is<WebCore::HTMLFormElement>(*e)) {
1546         DOMHTMLFormElement* newElement = new DOMHTMLFormElement(e);
1547         hr = newElement->QueryInterface(IID_IDOMElement, (void**)&domElement);
1548     } else if (e->hasTagName(iframeTag)) {
1549         DOMHTMLIFrameElement* newElement = new DOMHTMLIFrameElement(e);
1550         hr = newElement->QueryInterface(IID_IDOMElement, (void**)&domElement);
1551     } else if (is<WebCore::HTMLInputElement>(*e)) {
1552         DOMHTMLInputElement* newElement = new DOMHTMLInputElement(e);
1553         hr = newElement->QueryInterface(IID_IDOMElement, (void**)&domElement);
1554     } else if (is<WebCore::HTMLOptionElement>(*e)) {
1555         DOMHTMLOptionElement* newElement = new DOMHTMLOptionElement(e);
1556         hr = newElement->QueryInterface(IID_IDOMElement, (void**)&domElement);
1557     } else if (e->hasTagName(selectTag)) {
1558         DOMHTMLSelectElement* newElement = new DOMHTMLSelectElement(e);
1559         hr = newElement->QueryInterface(IID_IDOMElement, (void**)&domElement);
1560     } else if (is<WebCore::HTMLTextAreaElement>(*e)) {
1561         DOMHTMLTextAreaElement* newElement = new DOMHTMLTextAreaElement(e);
1562         hr = newElement->QueryInterface(IID_IDOMElement, (void**)&domElement);
1563     } else if (e->isHTMLElement()) {
1564         DOMHTMLElement* newElement = new DOMHTMLElement(e);
1565         hr = newElement->QueryInterface(IID_IDOMElement, (void**)&domElement);
1566     } else {
1567         DOMElement* newElement = new DOMElement(e);
1568         hr = newElement->QueryInterface(IID_IDOMElement, (void**)&domElement);
1569     }
1570
1571     if (FAILED(hr))
1572         return nullptr;
1573
1574     return domElement;
1575 }
1576
1577 // DOMRange - IUnknown -----------------------------------------------------
1578
1579 HRESULT DOMRange::QueryInterface(_In_ REFIID riid, _COM_Outptr_ void** ppvObject)
1580 {
1581     if (!ppvObject)
1582         return E_POINTER;
1583     *ppvObject = nullptr;
1584     if (IsEqualGUID(riid, IID_IDOMRange))
1585         *ppvObject = static_cast<IDOMRange*>(this);
1586     else
1587         return DOMObject::QueryInterface(riid, ppvObject);
1588
1589     AddRef();
1590     return S_OK;
1591 }
1592
1593 // DOMRange ----------------------------------------------------------------- 
1594
1595 DOMRange::DOMRange(WebCore::Range* e)
1596     : m_range(e)
1597 {
1598 }
1599
1600 DOMRange::~DOMRange()
1601 {
1602 }
1603
1604 IDOMRange* DOMRange::createInstance(WebCore::Range* range)
1605 {
1606     if (!range)
1607         return nullptr;
1608
1609     DOMRange* newRange = new DOMRange(range);
1610
1611     IDOMRange* domRange = nullptr;
1612     if (FAILED(newRange->QueryInterface(IID_IDOMRange, reinterpret_cast<void**>(&domRange))))
1613         return nullptr;
1614
1615     return newRange;
1616 }
1617
1618 HRESULT DOMRange::startContainer(_COM_Outptr_opt_ IDOMNode** node)
1619 {
1620     if (!node)
1621         return E_POINTER;
1622     *node = nullptr;
1623     if (!m_range)
1624         return E_UNEXPECTED;
1625
1626     *node = DOMNode::createInstance(&m_range->startContainer());
1627
1628     return S_OK;
1629 }
1630
1631 HRESULT DOMRange::startOffset(_Out_ int* offset)
1632 {
1633     if (!offset)
1634         return E_POINTER;
1635     *offset = 0;
1636     if (!m_range)
1637         return E_UNEXPECTED;
1638
1639     *offset = m_range->startOffset();
1640
1641     return S_OK;
1642 }
1643
1644 HRESULT DOMRange::endContainer(_COM_Outptr_opt_ IDOMNode** node)
1645 {
1646     if (!node)
1647         return E_POINTER;
1648     *node = nullptr;
1649     if (!m_range)
1650         return E_UNEXPECTED;
1651
1652     *node = DOMNode::createInstance(&m_range->endContainer());
1653
1654     return S_OK;
1655 }
1656
1657 HRESULT DOMRange::endOffset(_Out_ int* offset)
1658 {
1659     if (!offset)
1660         return E_POINTER;
1661     *offset = 0;
1662     if (!m_range)
1663         return E_UNEXPECTED;
1664
1665     *offset = m_range->endOffset();
1666
1667     return S_OK;
1668 }
1669
1670 HRESULT DOMRange::collapsed(_Out_ BOOL* result)
1671 {
1672     if (!result)
1673         return E_POINTER;
1674     *result = FALSE;
1675     if (!m_range)
1676         return E_UNEXPECTED;
1677
1678     *result = m_range->collapsed();
1679
1680     return S_OK;
1681 }
1682
1683 HRESULT DOMRange::commonAncestorContainer(_COM_Outptr_opt_ IDOMNode** container)
1684 {
1685     ASSERT_NOT_REACHED();
1686     if (!container)
1687         return E_POINTER;
1688     *container = nullptr;
1689     return E_NOTIMPL;
1690 }
1691
1692 HRESULT DOMRange::setStart(_In_opt_ IDOMNode* refNode, int offset)
1693 {
1694     ASSERT_NOT_REACHED();
1695     return E_NOTIMPL;
1696 }
1697
1698 HRESULT DOMRange::setEnd(_In_opt_ IDOMNode* refNode, int offset)
1699 {
1700     ASSERT_NOT_REACHED();
1701     return E_NOTIMPL;
1702 }
1703
1704 HRESULT DOMRange::setStartBefore(_In_opt_ IDOMNode* refNode)
1705 {
1706     ASSERT_NOT_REACHED();
1707     return E_NOTIMPL;
1708 }
1709
1710 HRESULT DOMRange::setStartAfter(_In_opt_ IDOMNode* refNode)
1711 {
1712     ASSERT_NOT_REACHED();
1713     return E_NOTIMPL;
1714 }
1715
1716 HRESULT DOMRange::setEndBefore(_In_opt_  IDOMNode* refNode)
1717 {
1718     ASSERT_NOT_REACHED();
1719     return E_NOTIMPL;
1720 }
1721
1722 HRESULT DOMRange::setEndAfter(_In_opt_  IDOMNode* refNode)
1723 {
1724     ASSERT_NOT_REACHED();
1725     return E_NOTIMPL;
1726 }
1727
1728 HRESULT DOMRange::collapse(BOOL toStart)
1729 {
1730     ASSERT_NOT_REACHED();
1731     return E_NOTIMPL;
1732 }
1733
1734 HRESULT DOMRange::selectNode(_In_opt_ IDOMNode* refNode)
1735 {
1736     ASSERT_NOT_REACHED();
1737     return E_NOTIMPL;
1738 }
1739
1740 HRESULT DOMRange::selectNodeContents(_In_opt_ IDOMNode* refNode)
1741 {
1742     ASSERT_NOT_REACHED();
1743     return E_NOTIMPL;
1744 }
1745
1746 HRESULT DOMRange::compareBoundaryPoints(unsigned short how, _In_opt_ IDOMRange* sourceRange)
1747 {
1748     ASSERT_NOT_REACHED();
1749     return E_NOTIMPL;
1750 }
1751
1752 HRESULT DOMRange::deleteContents()
1753 {
1754     ASSERT_NOT_REACHED();
1755     return E_NOTIMPL;
1756 }
1757
1758 HRESULT DOMRange::extractContents(_COM_Outptr_opt_ IDOMDocumentFragment** fragment)
1759 {
1760     ASSERT_NOT_REACHED();
1761     if (!fragment)
1762         return E_POINTER;
1763     *fragment = nullptr;
1764     return E_NOTIMPL;
1765 }
1766
1767 HRESULT DOMRange::cloneContents(_COM_Outptr_opt_ IDOMDocumentFragment** fragment)
1768 {
1769     ASSERT_NOT_REACHED();
1770     if (!fragment)
1771         return E_POINTER;
1772     *fragment = nullptr;
1773     return E_NOTIMPL;
1774 }
1775
1776 HRESULT DOMRange::insertNode(_In_opt_ IDOMNode* newNode)
1777 {
1778     ASSERT_NOT_REACHED();
1779     return E_NOTIMPL;
1780 }
1781
1782 HRESULT DOMRange::surroundContents(_In_opt_ IDOMNode* newParent)
1783 {
1784     ASSERT_NOT_REACHED();
1785     return E_NOTIMPL;
1786 }
1787
1788 HRESULT DOMRange::cloneRange(_COM_Outptr_opt_ IDOMRange** range)
1789 {
1790     ASSERT_NOT_REACHED();
1791     if (!range)
1792         return E_POINTER;
1793     *range = nullptr;
1794     return E_NOTIMPL;
1795 }
1796
1797 HRESULT DOMRange::toString(__deref_opt_out BSTR* str)
1798 {
1799     if (!str)
1800         return E_POINTER;
1801     *str = nullptr;
1802     if (!m_range)
1803         return E_UNEXPECTED;
1804
1805     *str = BString(m_range->toString()).release();
1806
1807     return S_OK;
1808 }
1809
1810 HRESULT DOMRange::detach()
1811 {
1812     ASSERT_NOT_REACHED();
1813     return E_NOTIMPL;
1814 }
1815
1816 DOMNamedNodeMap::DOMNamedNodeMap(WebCore::NamedNodeMap* nodeMap)
1817     : m_nodeMap(nodeMap)
1818 {
1819 }
1820
1821 DOMNamedNodeMap::~DOMNamedNodeMap()
1822 {
1823 }
1824
1825 IDOMNamedNodeMap* DOMNamedNodeMap::createInstance(WebCore::NamedNodeMap* nodeMap)
1826 {
1827     if (!nodeMap)
1828         return nullptr;
1829
1830     DOMNamedNodeMap* namedNodeMap = new DOMNamedNodeMap(nodeMap);
1831
1832     IDOMNamedNodeMap* domNamedNodeMap = nullptr;
1833     if (FAILED(namedNodeMap->QueryInterface(IID_IDOMNamedNodeMap, reinterpret_cast<void**>(&domNamedNodeMap))))
1834         return nullptr;
1835
1836     return namedNodeMap;
1837 }
1838
1839 HRESULT DOMNamedNodeMap::QueryInterface(_In_ REFIID riid, _COM_Outptr_ void** ppvObject)
1840 {
1841     *ppvObject = nullptr;
1842     if (IsEqualGUID(riid, IID_IDOMNamedNodeMap))
1843         *ppvObject = static_cast<IDOMNamedNodeMap*>(this);
1844     else
1845         return DOMObject::QueryInterface(riid, ppvObject);
1846
1847     AddRef();
1848     return S_OK;
1849 }
1850
1851 HRESULT DOMNamedNodeMap::getNamedItem(_In_ BSTR name, _COM_Outptr_opt_ IDOMNode** result)
1852 {
1853     return E_NOTIMPL;
1854 }
1855
1856 HRESULT DOMNamedNodeMap::setNamedItem(_In_opt_ IDOMNode* arg, _COM_Outptr_opt_ IDOMNode** result)
1857 {
1858     return E_NOTIMPL;
1859 }
1860
1861 HRESULT DOMNamedNodeMap::removeNamedItem(_In_ BSTR name, _COM_Outptr_opt_ IDOMNode** result)
1862 {
1863     return E_NOTIMPL;
1864 }
1865
1866 HRESULT DOMNamedNodeMap::item(_In_ UINT index, _COM_Outptr_opt_ IDOMNode** result)
1867 {
1868     if (!result)
1869         return E_POINTER;
1870     
1871     if (!m_nodeMap)
1872         return E_FAIL;
1873
1874     *result = DOMNode::createInstance(m_nodeMap->item(index).get());
1875     return *result ? S_OK : E_FAIL;
1876 }
1877
1878 HRESULT DOMNamedNodeMap::length(_Out_opt_ UINT* result)
1879 {
1880     if (!result)
1881         return E_POINTER;
1882
1883     *result = m_nodeMap->length();
1884     return S_OK;
1885 }
1886
1887 HRESULT DOMNamedNodeMap::getNamedItemNS(_In_ BSTR namespaceURI, _In_ BSTR localName, _COM_Outptr_opt_ IDOMNode** result)
1888 {
1889     return E_NOTIMPL;
1890 }
1891
1892 HRESULT DOMNamedNodeMap::setNamedItemNS(_In_opt_ IDOMNode* arg, _COM_Outptr_opt_ IDOMNode** result)
1893 {
1894     return E_NOTIMPL;
1895 }
1896
1897 HRESULT DOMNamedNodeMap::removeNamedItemNS(_In_ BSTR namespaceURI, _In_ BSTR localName, _COM_Outptr_opt_ IDOMNode** result)
1898 {
1899     return E_NOTIMPL;
1900 }