1/*
2 * Copyright (C) 2006, 2007, 2009 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 COMPUTER, 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 COMPUTER, 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 "config.h"
27#include "WebKitDLL.h"
28#include "DOMCoreClasses.h"
29
30#include "DOMCSSClasses.h"
31#include "DOMEventsClasses.h"
32#include "DOMHTMLClasses.h"
33#include "WebKitGraphics.h"
34
35#include <WebCore/BString.h>
36#include <WebCore/COMPtr.h>
37#include <WebCore/DOMWindow.h>
38#include <WebCore/Document.h>
39#include <WebCore/Element.h>
40#include <WebCore/Frame.h>
41#include <WebCore/SimpleFontData.h>
42#include <WebCore/HTMLFormElement.h>
43#include <WebCore/HTMLInputElement.h>
44#include <WebCore/HTMLNames.h>
45#include <WebCore/HTMLOptionElement.h>
46#include <WebCore/HTMLSelectElement.h>
47#include <WebCore/HTMLTextAreaElement.h>
48#include <WebCore/NodeList.h>
49#include <WebCore/RenderObject.h>
50#include <WebCore/RenderTreeAsText.h>
51
52#include <initguid.h>
53// {3B0C0EFF-478B-4b0b-8290-D2321E08E23E}
54DEFINE_GUID(IID_DOMElement, 0x3b0c0eff, 0x478b, 0x4b0b, 0x82, 0x90, 0xd2, 0x32, 0x1e, 0x8, 0xe2, 0x3e);
55
56// Our normal style is just to say "using namespace WebCore" rather than having
57// individual using directives for each type from that namespace. But
58// "DOMObject" exists both in the WebCore namespace and unnamespaced in this
59// file, which leads to ambiguities if we say "using namespace WebCore".
60using namespace WebCore::HTMLNames;
61using WTF::AtomicString;
62using WebCore::BString;
63using WebCore::Element;
64using WebCore::ExceptionCode;
65using WebCore::FontDescription;
66using WebCore::Frame;
67using WebCore::IntRect;
68using WTF::String;
69
70// DOMObject - IUnknown -------------------------------------------------------
71
72HRESULT STDMETHODCALLTYPE DOMObject::QueryInterface(REFIID riid, void** ppvObject)
73{
74    *ppvObject = 0;
75    if (IsEqualGUID(riid, IID_IDOMObject))
76        *ppvObject = static_cast<IDOMObject*>(this);
77    else
78        return WebScriptObject::QueryInterface(riid, ppvObject);
79
80    AddRef();
81    return S_OK;
82}
83
84// DOMNode - IUnknown ---------------------------------------------------------
85
86HRESULT STDMETHODCALLTYPE DOMNode::QueryInterface(REFIID riid, void** ppvObject)
87{
88    *ppvObject = 0;
89    if (IsEqualGUID(riid, IID_IDOMNode))
90        *ppvObject = static_cast<IDOMNode*>(this);
91    else if (IsEqualGUID(riid, __uuidof(DOMNode)))
92        *ppvObject = static_cast<DOMNode*>(this);
93    else
94        return DOMObject::QueryInterface(riid, ppvObject);
95
96    AddRef();
97    return S_OK;
98}
99
100// DOMNode --------------------------------------------------------------------
101
102HRESULT STDMETHODCALLTYPE DOMNode::nodeName(
103    /* [retval][out] */ BSTR* result)
104{
105    if (!result)
106        return E_POINTER;
107
108    if (!m_node)
109        return E_FAIL;
110
111    *result = BString(m_node->nodeName()).release();
112    return S_OK;
113}
114
115HRESULT STDMETHODCALLTYPE DOMNode::nodeValue(
116    /* [retval][out] */ BSTR* result)
117{
118    if (!m_node)
119        return E_FAIL;
120    WTF::String nodeValueStr = m_node->nodeValue();
121    *result = SysAllocStringLen(nodeValueStr.characters(), nodeValueStr.length());
122    if (nodeValueStr.length() && !*result)
123        return E_OUTOFMEMORY;
124    return S_OK;
125}
126
127HRESULT STDMETHODCALLTYPE DOMNode::setNodeValue(
128    /* [in] */ BSTR /*value*/)
129{
130    ASSERT_NOT_REACHED();
131    return E_NOTIMPL;
132}
133
134HRESULT STDMETHODCALLTYPE DOMNode::nodeType(
135    /* [retval][out] */ unsigned short* /*result*/)
136{
137    ASSERT_NOT_REACHED();
138    return E_NOTIMPL;
139}
140
141HRESULT STDMETHODCALLTYPE DOMNode::parentNode(
142    /* [retval][out] */ IDOMNode** result)
143{
144    *result = 0;
145    if (!m_node || !m_node->parentNode())
146        return E_FAIL;
147    *result = DOMNode::createInstance(m_node->parentNode());
148    return *result ? S_OK : E_FAIL;
149}
150
151HRESULT STDMETHODCALLTYPE DOMNode::childNodes(
152    /* [retval][out] */ IDOMNodeList** result)
153{
154    if (!m_node)
155        return E_FAIL;
156
157    if (!result)
158        return E_POINTER;
159
160    *result = DOMNodeList::createInstance(m_node->childNodes().get());
161    return *result ? S_OK : E_FAIL;
162}
163
164HRESULT STDMETHODCALLTYPE DOMNode::firstChild(
165    /* [retval][out] */ IDOMNode** /*result*/)
166{
167    ASSERT_NOT_REACHED();
168    return E_NOTIMPL;
169}
170
171HRESULT STDMETHODCALLTYPE DOMNode::lastChild(
172    /* [retval][out] */ IDOMNode** /*result*/)
173{
174    ASSERT_NOT_REACHED();
175    return E_NOTIMPL;
176}
177
178HRESULT STDMETHODCALLTYPE DOMNode::previousSibling(
179    /* [retval][out] */ IDOMNode** /*result*/)
180{
181    ASSERT_NOT_REACHED();
182    return E_NOTIMPL;
183}
184
185HRESULT STDMETHODCALLTYPE DOMNode::nextSibling(
186    /* [retval][out] */ IDOMNode** result)
187{
188    if (!result)
189        return E_POINTER;
190    *result = 0;
191    if (!m_node)
192        return E_FAIL;
193    *result = DOMNode::createInstance(m_node->nextSibling());
194    return *result ? S_OK : E_FAIL;
195}
196
197HRESULT STDMETHODCALLTYPE DOMNode::attributes(
198    /* [retval][out] */ IDOMNamedNodeMap** /*result*/)
199{
200    ASSERT_NOT_REACHED();
201    return E_NOTIMPL;
202}
203
204HRESULT STDMETHODCALLTYPE DOMNode::ownerDocument(
205    /* [retval][out] */ IDOMDocument** result)
206{
207    if (!result)
208        return E_POINTER;
209    *result = 0;
210    if (!m_node)
211        return E_FAIL;
212    *result = DOMDocument::createInstance(m_node->ownerDocument());
213    return *result ? S_OK : E_FAIL;
214}
215
216HRESULT STDMETHODCALLTYPE DOMNode::insertBefore(
217    /* [in] */ IDOMNode* newChild,
218    /* [in] */ IDOMNode* refChild,
219    /* [retval][out] */ IDOMNode** result)
220{
221    if (!result)
222        return E_POINTER;
223
224    *result = 0;
225
226    if (!m_node)
227        return E_FAIL;
228
229    COMPtr<DOMNode> newChildNode(Query, newChild);
230    if (!newChildNode)
231        return E_FAIL;
232
233    COMPtr<DOMNode> refChildNode(Query, refChild);
234
235    ExceptionCode ec;
236    if (!m_node->insertBefore(newChildNode->node(), refChildNode ? refChildNode->node() : 0, ec))
237        return E_FAIL;
238
239    *result = newChild;
240    (*result)->AddRef();
241    return S_OK;
242}
243
244HRESULT STDMETHODCALLTYPE DOMNode::replaceChild(
245    /* [in] */ IDOMNode* /*newChild*/,
246    /* [in] */ IDOMNode* /*oldChild*/,
247    /* [retval][out] */ IDOMNode** /*result*/)
248{
249    ASSERT_NOT_REACHED();
250    return E_NOTIMPL;
251}
252
253HRESULT STDMETHODCALLTYPE DOMNode::removeChild(
254    /* [in] */ IDOMNode* oldChild,
255    /* [retval][out] */ IDOMNode** result)
256{
257    if (!result)
258        return E_POINTER;
259
260    *result = 0;
261
262    if (!m_node)
263        return E_FAIL;
264
265    COMPtr<DOMNode> oldChildNode(Query, oldChild);
266    if (!oldChildNode)
267        return E_FAIL;
268
269    ExceptionCode ec;
270    if (!m_node->removeChild(oldChildNode->node(), ec))
271        return E_FAIL;
272
273    *result = oldChild;
274    (*result)->AddRef();
275    return S_OK;
276}
277
278HRESULT STDMETHODCALLTYPE DOMNode::appendChild(
279    /* [in] */ IDOMNode* /*oldChild*/,
280    /* [retval][out] */ IDOMNode** /*result*/)
281{
282    ASSERT_NOT_REACHED();
283    return E_NOTIMPL;
284}
285
286HRESULT STDMETHODCALLTYPE DOMNode::hasChildNodes(
287    /* [retval][out] */ BOOL* /*result*/)
288{
289    ASSERT_NOT_REACHED();
290    return E_NOTIMPL;
291}
292
293HRESULT STDMETHODCALLTYPE DOMNode::cloneNode(
294    /* [in] */ BOOL /*deep*/,
295    /* [retval][out] */ IDOMNode** /*result*/)
296{
297    ASSERT_NOT_REACHED();
298    return E_NOTIMPL;
299}
300
301HRESULT STDMETHODCALLTYPE DOMNode::normalize( void)
302{
303    ASSERT_NOT_REACHED();
304    return E_NOTIMPL;
305}
306
307HRESULT STDMETHODCALLTYPE DOMNode::isSupported(
308    /* [in] */ BSTR /*feature*/,
309    /* [in] */ BSTR /*version*/,
310    /* [retval][out] */ BOOL* /*result*/)
311{
312    ASSERT_NOT_REACHED();
313    return E_NOTIMPL;
314}
315
316HRESULT STDMETHODCALLTYPE DOMNode::namespaceURI(
317    /* [retval][out] */ BSTR* /*result*/)
318{
319    ASSERT_NOT_REACHED();
320    return E_NOTIMPL;
321}
322
323HRESULT STDMETHODCALLTYPE DOMNode::prefix(
324    /* [retval][out] */ BSTR* /*result*/)
325{
326    ASSERT_NOT_REACHED();
327    return E_NOTIMPL;
328}
329
330HRESULT STDMETHODCALLTYPE DOMNode::setPrefix(
331    /* [in] */ BSTR /*prefix*/)
332{
333    ASSERT_NOT_REACHED();
334    return E_NOTIMPL;
335}
336
337HRESULT STDMETHODCALLTYPE DOMNode::localName(
338    /* [retval][out] */ BSTR* /*result*/)
339{
340    ASSERT_NOT_REACHED();
341    return E_NOTIMPL;
342}
343
344HRESULT STDMETHODCALLTYPE DOMNode::hasAttributes(
345    /* [retval][out] */ BOOL* /*result*/)
346{
347    ASSERT_NOT_REACHED();
348    return E_NOTIMPL;
349}
350
351HRESULT STDMETHODCALLTYPE DOMNode::isSameNode(
352    /* [in] */ IDOMNode* other,
353    /* [retval][out] */ BOOL* result)
354{
355    if (!result) {
356        ASSERT_NOT_REACHED();
357        return E_POINTER;
358    }
359
360    *result = FALSE;
361
362    if (!other)
363        return E_POINTER;
364
365    COMPtr<DOMNode> domOther;
366    HRESULT hr = other->QueryInterface(__uuidof(DOMNode), (void**)&domOther);
367    if (FAILED(hr))
368        return hr;
369
370    *result = m_node->isSameNode(domOther->node()) ? TRUE : FALSE;
371    return S_OK;
372}
373
374HRESULT STDMETHODCALLTYPE DOMNode::isEqualNode(
375    /* [in] */ IDOMNode* /*other*/,
376    /* [retval][out] */ BOOL* /*result*/)
377{
378    ASSERT_NOT_REACHED();
379    return E_NOTIMPL;
380}
381
382HRESULT STDMETHODCALLTYPE DOMNode::textContent(
383    /* [retval][out] */ BSTR* result)
384{
385    if (!result)
386        return E_POINTER;
387
388    *result = BString(m_node->textContent()).release();
389
390    return S_OK;
391}
392
393HRESULT STDMETHODCALLTYPE DOMNode::setTextContent(
394    /* [in] */ BSTR /*text*/)
395{
396    ASSERT_NOT_REACHED();
397    return E_NOTIMPL;
398}
399
400// DOMNode - IDOMEventTarget --------------------------------------------------
401
402HRESULT STDMETHODCALLTYPE DOMNode::addEventListener(
403    /* [in] */ BSTR /*type*/,
404    /* [in] */ IDOMEventListener* /*listener*/,
405    /* [in] */ BOOL /*useCapture*/)
406{
407    return E_NOTIMPL;
408}
409
410HRESULT STDMETHODCALLTYPE DOMNode::removeEventListener(
411    /* [in] */ BSTR /*type*/,
412    /* [in] */ IDOMEventListener* /*listener*/,
413    /* [in] */ BOOL /*useCapture*/)
414{
415    return E_NOTIMPL;
416}
417
418HRESULT STDMETHODCALLTYPE DOMNode::dispatchEvent(
419    /* [in] */ IDOMEvent* evt,
420    /* [retval][out] */ BOOL* result)
421{
422    if (!m_node || !evt)
423        return E_FAIL;
424
425#if 0   // FIXME - raise dom exceptions
426    if (![self _node]->isEventTargetNode())
427        WebCore::raiseDOMException(DOM_NOT_SUPPORTED_ERR);
428#endif
429
430    COMPtr<DOMEvent> domEvent;
431    HRESULT hr = evt->QueryInterface(IID_DOMEvent, (void**) &domEvent);
432    if (FAILED(hr))
433        return hr;
434
435    WebCore::ExceptionCode ec = 0;
436    *result = m_node->dispatchEvent(domEvent->coreEvent(), ec) ? TRUE : FALSE;
437#if 0   // FIXME - raise dom exceptions
438    WebCore::raiseOnDOMError(ec);
439#endif
440    return S_OK;
441}
442
443// DOMNode - DOMNode ----------------------------------------------------------
444
445DOMNode::DOMNode(WebCore::Node* n)
446: m_node(0)
447{
448    if (n)
449        n->ref();
450
451    m_node = n;
452}
453
454DOMNode::~DOMNode()
455{
456    if (m_node)
457        m_node->deref();
458}
459
460IDOMNode* DOMNode::createInstance(WebCore::Node* n)
461{
462    if (!n)
463        return 0;
464
465    HRESULT hr = S_OK;
466    IDOMNode* domNode = 0;
467    WebCore::Node::NodeType nodeType = n->nodeType();
468
469    switch (nodeType) {
470        case WebCore::Node::ELEMENT_NODE:
471        {
472            IDOMElement* newElement = DOMElement::createInstance(static_cast<WebCore::Element*>(n));
473            if (newElement) {
474                hr = newElement->QueryInterface(IID_IDOMNode, (void**)&domNode);
475                newElement->Release();
476            }
477        }
478        break;
479        case WebCore::Node::DOCUMENT_NODE:
480        {
481            IDOMDocument* newDocument = DOMDocument::createInstance(n->document());
482            if (newDocument) {
483                hr = newDocument->QueryInterface(IID_IDOMNode, (void**)&domNode);
484                newDocument->Release();
485            }
486        }
487        break;
488        default:
489        {
490            DOMNode* newNode = new DOMNode(n);
491            hr = newNode->QueryInterface(IID_IDOMNode, (void**)&domNode);
492        }
493        break;
494    }
495
496    if (FAILED(hr))
497        return 0;
498
499    return domNode;
500}
501
502// DOMNodeList - IUnknown -----------------------------------------------------
503
504HRESULT STDMETHODCALLTYPE DOMNodeList::QueryInterface(REFIID riid, void** ppvObject)
505{
506    *ppvObject = 0;
507    if (IsEqualGUID(riid, IID_IDOMNodeList))
508        *ppvObject = static_cast<IDOMNodeList*>(this);
509    else
510        return DOMObject::QueryInterface(riid, ppvObject);
511
512    AddRef();
513    return S_OK;
514}
515
516// IDOMNodeList ---------------------------------------------------------------
517
518HRESULT STDMETHODCALLTYPE DOMNodeList::item(
519    /* [in] */ UINT index,
520    /* [retval][out] */ IDOMNode **result)
521{
522    *result = 0;
523    if (!m_nodeList)
524        return E_FAIL;
525
526    WebCore::Node* itemNode = m_nodeList->item(index);
527    if (!itemNode)
528        return E_FAIL;
529
530    *result = DOMNode::createInstance(itemNode);
531    return *result ? S_OK : E_FAIL;
532}
533
534HRESULT STDMETHODCALLTYPE DOMNodeList::length(
535        /* [retval][out] */ UINT *result)
536{
537    *result = 0;
538    if (!m_nodeList)
539        return E_FAIL;
540    *result = m_nodeList->length();
541    return S_OK;
542}
543
544// DOMNodeList - DOMNodeList --------------------------------------------------
545
546DOMNodeList::DOMNodeList(WebCore::NodeList* l)
547: m_nodeList(0)
548{
549    if (l)
550        l->ref();
551
552    m_nodeList = l;
553}
554
555DOMNodeList::~DOMNodeList()
556{
557    if (m_nodeList)
558        m_nodeList->deref();
559}
560
561IDOMNodeList* DOMNodeList::createInstance(WebCore::NodeList* l)
562{
563    if (!l)
564        return 0;
565
566    IDOMNodeList* domNodeList = 0;
567    DOMNodeList* newNodeList = new DOMNodeList(l);
568    if (FAILED(newNodeList->QueryInterface(IID_IDOMNodeList, (void**)&domNodeList)))
569        return 0;
570
571    return domNodeList;
572}
573
574// DOMDocument - IUnknown -----------------------------------------------------
575
576HRESULT STDMETHODCALLTYPE DOMDocument::QueryInterface(REFIID riid, void** ppvObject)
577{
578    *ppvObject = 0;
579    if (IsEqualGUID(riid, IID_IDOMDocument))
580        *ppvObject = static_cast<IDOMDocument*>(this);
581    else if (IsEqualGUID(riid, IID_IDOMViewCSS))
582        *ppvObject = static_cast<IDOMViewCSS*>(this);
583    else if (IsEqualGUID(riid, IID_IDOMDocumentEvent))
584        *ppvObject = static_cast<IDOMDocumentEvent*>(this);
585    else
586        return DOMNode::QueryInterface(riid, ppvObject);
587
588    AddRef();
589    return S_OK;
590}
591
592// DOMDocument ----------------------------------------------------------------
593
594HRESULT STDMETHODCALLTYPE DOMDocument::doctype(
595    /* [retval][out] */ IDOMDocumentType** /*result*/)
596{
597    ASSERT_NOT_REACHED();
598    return E_NOTIMPL;
599}
600
601HRESULT STDMETHODCALLTYPE DOMDocument::implementation(
602    /* [retval][out] */ IDOMImplementation** /*result*/)
603{
604    ASSERT_NOT_REACHED();
605    return E_NOTIMPL;
606}
607
608HRESULT STDMETHODCALLTYPE DOMDocument::documentElement(
609    /* [retval][out] */ IDOMElement** result)
610{
611    *result = DOMElement::createInstance(m_document->documentElement());
612    return *result ? S_OK : E_FAIL;
613}
614
615HRESULT STDMETHODCALLTYPE DOMDocument::createElement(
616    /* [in] */ BSTR tagName,
617    /* [retval][out] */ IDOMElement** result)
618{
619    if (!m_document)
620        return E_FAIL;
621
622    String tagNameString(tagName);
623    ExceptionCode ec;
624    *result = DOMElement::createInstance(m_document->createElement(tagNameString, ec).get());
625    return *result ? S_OK : E_FAIL;
626}
627
628HRESULT STDMETHODCALLTYPE DOMDocument::createDocumentFragment(
629    /* [retval][out] */ IDOMDocumentFragment** /*result*/)
630{
631    ASSERT_NOT_REACHED();
632    return E_NOTIMPL;
633}
634
635HRESULT STDMETHODCALLTYPE DOMDocument::createTextNode(
636    /* [in] */ BSTR /*data*/,
637    /* [retval][out] */ IDOMText** /*result*/)
638{
639    ASSERT_NOT_REACHED();
640    return E_NOTIMPL;
641}
642
643HRESULT STDMETHODCALLTYPE DOMDocument::createComment(
644    /* [in] */ BSTR /*data*/,
645    /* [retval][out] */ IDOMComment** /*result*/)
646{
647    ASSERT_NOT_REACHED();
648    return E_NOTIMPL;
649}
650
651HRESULT STDMETHODCALLTYPE DOMDocument::createCDATASection(
652    /* [in] */ BSTR /*data*/,
653    /* [retval][out] */ IDOMCDATASection** /*result*/)
654{
655    ASSERT_NOT_REACHED();
656    return E_NOTIMPL;
657}
658
659HRESULT STDMETHODCALLTYPE DOMDocument::createProcessingInstruction(
660    /* [in] */ BSTR /*target*/,
661    /* [in] */ BSTR /*data*/,
662    /* [retval][out] */ IDOMProcessingInstruction** /*result*/)
663{
664    ASSERT_NOT_REACHED();
665    return E_NOTIMPL;
666}
667
668HRESULT STDMETHODCALLTYPE DOMDocument::createAttribute(
669    /* [in] */ BSTR /*name*/,
670    /* [retval][out] */ IDOMAttr** /*result*/)
671{
672    ASSERT_NOT_REACHED();
673    return E_NOTIMPL;
674}
675
676HRESULT STDMETHODCALLTYPE DOMDocument::createEntityReference(
677    /* [in] */ BSTR /*name*/,
678    /* [retval][out] */ IDOMEntityReference** /*result*/)
679{
680    ASSERT_NOT_REACHED();
681    return E_NOTIMPL;
682}
683
684HRESULT STDMETHODCALLTYPE DOMDocument::getElementsByTagName(
685    /* [in] */ BSTR tagName,
686    /* [retval][out] */ IDOMNodeList** result)
687{
688    if (!m_document)
689        return E_FAIL;
690
691    String tagNameString(tagName);
692    *result = DOMNodeList::createInstance(m_document->getElementsByTagName(tagNameString).get());
693    return *result ? S_OK : E_FAIL;
694}
695
696HRESULT STDMETHODCALLTYPE DOMDocument::importNode(
697    /* [in] */ IDOMNode* /*importedNode*/,
698    /* [in] */ BOOL /*deep*/,
699    /* [retval][out] */ IDOMNode** /*result*/)
700{
701    ASSERT_NOT_REACHED();
702    return E_NOTIMPL;
703}
704
705HRESULT STDMETHODCALLTYPE DOMDocument::createElementNS(
706    /* [in] */ BSTR /*namespaceURI*/,
707    /* [in] */ BSTR /*qualifiedName*/,
708    /* [retval][out] */ IDOMElement** /*result*/)
709{
710    ASSERT_NOT_REACHED();
711    return E_NOTIMPL;
712}
713
714HRESULT STDMETHODCALLTYPE DOMDocument::createAttributeNS(
715    /* [in] */ BSTR /*namespaceURI*/,
716    /* [in] */ BSTR /*qualifiedName*/,
717    /* [retval][out] */ IDOMAttr** /*result*/)
718{
719    ASSERT_NOT_REACHED();
720    return E_NOTIMPL;
721}
722
723HRESULT STDMETHODCALLTYPE DOMDocument::getElementsByTagNameNS(
724    /* [in] */ BSTR namespaceURI,
725    /* [in] */ BSTR localName,
726    /* [retval][out] */ IDOMNodeList** result)
727{
728    if (!m_document)
729        return E_FAIL;
730
731    String namespaceURIString(namespaceURI);
732    String localNameString(localName);
733    *result = DOMNodeList::createInstance(m_document->getElementsByTagNameNS(namespaceURIString, localNameString).get());
734    return *result ? S_OK : E_FAIL;
735}
736
737HRESULT STDMETHODCALLTYPE DOMDocument::getElementById(
738    /* [in] */ BSTR elementId,
739    /* [retval][out] */ IDOMElement** result)
740{
741    if (!m_document)
742        return E_FAIL;
743
744    String idString(elementId);
745    *result = DOMElement::createInstance(m_document->getElementById(idString));
746    return *result ? S_OK : E_FAIL;
747}
748
749// DOMDocument - IDOMViewCSS --------------------------------------------------
750
751HRESULT STDMETHODCALLTYPE DOMDocument::getComputedStyle(
752    /* [in] */ IDOMElement* elt,
753    /* [in] */ BSTR pseudoElt,
754    /* [retval][out] */ IDOMCSSStyleDeclaration** result)
755{
756    if (!elt || !result)
757        return E_POINTER;
758
759    COMPtr<DOMElement> domEle;
760    HRESULT hr = elt->QueryInterface(IID_DOMElement, (void**)&domEle);
761    if (FAILED(hr))
762        return hr;
763    Element* element = domEle->element();
764
765    WebCore::DOMWindow* dv = m_document->defaultView();
766    String pseudoEltString(pseudoElt);
767
768    if (!dv)
769        return E_FAIL;
770
771    *result = DOMCSSStyleDeclaration::createInstance(dv->getComputedStyle(element, pseudoEltString.impl()).get());
772    return *result ? S_OK : E_FAIL;
773}
774
775// DOMDocument - IDOMDocumentEvent --------------------------------------------
776
777HRESULT STDMETHODCALLTYPE DOMDocument::createEvent(
778    /* [in] */ BSTR eventType,
779    /* [retval][out] */ IDOMEvent **result)
780{
781    String eventTypeString(eventType, SysStringLen(eventType));
782    WebCore::ExceptionCode ec = 0;
783    *result = DOMEvent::createInstance(m_document->createEvent(eventTypeString, ec));
784    return *result ? S_OK : E_FAIL;
785}
786
787// DOMDocument - DOMDocument --------------------------------------------------
788
789DOMDocument::DOMDocument(WebCore::Document* d)
790: DOMNode(d)
791, m_document(d)
792{
793}
794
795DOMDocument::~DOMDocument()
796{
797}
798
799IDOMDocument* DOMDocument::createInstance(WebCore::Document* d)
800{
801    if (!d)
802        return 0;
803
804    HRESULT hr;
805    IDOMDocument* domDocument = 0;
806
807    if (d->isHTMLDocument()) {
808        DOMHTMLDocument* newDocument = new DOMHTMLDocument(d);
809        hr = newDocument->QueryInterface(IID_IDOMDocument, (void**)&domDocument);
810    } else {
811        DOMDocument* newDocument = new DOMDocument(d);
812        hr = newDocument->QueryInterface(IID_IDOMDocument, (void**)&domDocument);
813    }
814
815    if (FAILED(hr))
816        return 0;
817
818    return domDocument;
819}
820
821// DOMElement - IUnknown ------------------------------------------------------
822
823HRESULT STDMETHODCALLTYPE DOMElement::QueryInterface(REFIID riid, void** ppvObject)
824{
825    *ppvObject = 0;
826    if (IsEqualGUID(riid, IID_IDOMElement))
827        *ppvObject = static_cast<IDOMElement*>(this);
828    else if (IsEqualGUID(riid, IID_DOMElement))
829        *ppvObject = static_cast<DOMElement*>(this);
830    else if (IsEqualGUID(riid, IID_IDOMElementPrivate))
831        *ppvObject = static_cast<IDOMElementPrivate*>(this);
832    else if (IsEqualGUID(riid, IID_IDOMNodeExtensions))
833        *ppvObject = static_cast<IDOMNodeExtensions*>(this);
834    else if (IsEqualGUID(riid, IID_IDOMElementCSSInlineStyle))
835        *ppvObject = static_cast<IDOMElementCSSInlineStyle*>(this);
836    else if (IsEqualGUID(riid, IID_IDOMElementExtensions))
837        *ppvObject = static_cast<IDOMElementExtensions*>(this);
838    else
839        return DOMNode::QueryInterface(riid, ppvObject);
840
841    AddRef();
842    return S_OK;
843}
844
845// DOMElement - IDOMNodeExtensions---------------------------------------------
846
847HRESULT STDMETHODCALLTYPE DOMElement::boundingBox(
848    /* [retval][out] */ LPRECT rect)
849{
850    ::SetRectEmpty(rect);
851
852    if (!m_element)
853        return E_FAIL;
854
855    WebCore::RenderObject *renderer = m_element->renderer();
856    if (renderer) {
857        IntRect boundsIntRect = renderer->absoluteBoundingBoxRect();
858        rect->left = boundsIntRect.x();
859        rect->top = boundsIntRect.y();
860        rect->right = boundsIntRect.x() + boundsIntRect.width();
861        rect->bottom = boundsIntRect.y() + boundsIntRect.height();
862    }
863
864    return S_OK;
865}
866
867HRESULT STDMETHODCALLTYPE DOMElement::lineBoxRects(
868    /* [size_is][in] */ RECT* /*rects*/,
869    /* [in] */ int /*cRects*/)
870{
871    return E_NOTIMPL;
872}
873
874// IDOMElement ----------------------------------------------------------------
875
876HRESULT STDMETHODCALLTYPE DOMElement::tagName(
877        /* [retval][out] */ BSTR* result)
878{
879    if (!m_element)
880        return E_FAIL;
881
882    if (!result)
883        return E_POINTER;
884
885    *result = BString(m_element->tagName()).release();
886    return S_OK;
887}
888
889HRESULT STDMETHODCALLTYPE DOMElement::getAttribute(
890        /* [in] */ BSTR name,
891        /* [retval][out] */ BSTR* result)
892{
893    if (!m_element)
894        return E_FAIL;
895    WTF::String nameString(name, SysStringLen(name));
896    WTF::String& attrValueString = (WTF::String&) m_element->getAttribute(nameString);
897    *result = SysAllocStringLen(attrValueString.characters(), attrValueString.length());
898    if (attrValueString.length() && !*result)
899        return E_OUTOFMEMORY;
900    return S_OK;
901}
902
903HRESULT STDMETHODCALLTYPE DOMElement::setAttribute(
904        /* [in] */ BSTR name,
905        /* [in] */ BSTR value)
906{
907    if (!m_element)
908        return E_FAIL;
909
910    WTF::String nameString(name, SysStringLen(name));
911    WTF::String valueString(value, SysStringLen(value));
912    WebCore::ExceptionCode ec = 0;
913    m_element->setAttribute(nameString, valueString, ec);
914    return ec ? E_FAIL : S_OK;
915}
916
917HRESULT STDMETHODCALLTYPE DOMElement::removeAttribute(
918        /* [in] */ BSTR /*name*/)
919{
920    ASSERT_NOT_REACHED();
921    return E_NOTIMPL;
922}
923
924HRESULT STDMETHODCALLTYPE DOMElement::getAttributeNode(
925        /* [in] */ BSTR /*name*/,
926        /* [retval][out] */ IDOMAttr** /*result*/)
927{
928    ASSERT_NOT_REACHED();
929    return E_NOTIMPL;
930}
931
932HRESULT STDMETHODCALLTYPE DOMElement::setAttributeNode(
933        /* [in] */ IDOMAttr* /*newAttr*/,
934        /* [retval][out] */ IDOMAttr** /*result*/)
935{
936    ASSERT_NOT_REACHED();
937    return E_NOTIMPL;
938}
939
940HRESULT STDMETHODCALLTYPE DOMElement::removeAttributeNode(
941        /* [in] */ IDOMAttr* /*oldAttr*/,
942        /* [retval][out] */ IDOMAttr** /*result*/)
943{
944    ASSERT_NOT_REACHED();
945    return E_NOTIMPL;
946}
947
948HRESULT STDMETHODCALLTYPE DOMElement::getElementsByTagName(
949        /* [in] */ BSTR /*name*/,
950        /* [retval][out] */ IDOMNodeList** /*result*/)
951{
952    ASSERT_NOT_REACHED();
953    return E_NOTIMPL;
954}
955
956HRESULT STDMETHODCALLTYPE DOMElement::getAttributeNS(
957        /* [in] */ BSTR /*namespaceURI*/,
958        /* [in] */ BSTR /*localName*/,
959        /* [retval][out] */ BSTR* /*result*/)
960{
961    ASSERT_NOT_REACHED();
962    return E_NOTIMPL;
963}
964
965HRESULT STDMETHODCALLTYPE DOMElement::setAttributeNS(
966        /* [in] */ BSTR /*namespaceURI*/,
967        /* [in] */ BSTR /*qualifiedName*/,
968        /* [in] */ BSTR /*value*/)
969{
970    ASSERT_NOT_REACHED();
971    return E_NOTIMPL;
972}
973
974HRESULT STDMETHODCALLTYPE DOMElement::removeAttributeNS(
975        /* [in] */ BSTR /*namespaceURI*/,
976        /* [in] */ BSTR /*localName*/)
977{
978    ASSERT_NOT_REACHED();
979    return E_NOTIMPL;
980}
981
982HRESULT STDMETHODCALLTYPE DOMElement::getAttributeNodeNS(
983        /* [in] */ BSTR /*namespaceURI*/,
984        /* [in] */ BSTR /*localName*/,
985        /* [retval][out] */ IDOMAttr** /*result*/)
986{
987    ASSERT_NOT_REACHED();
988    return E_NOTIMPL;
989}
990
991HRESULT STDMETHODCALLTYPE DOMElement::setAttributeNodeNS(
992        /* [in] */ IDOMAttr* /*newAttr*/,
993        /* [retval][out] */ IDOMAttr** /*result*/)
994{
995    ASSERT_NOT_REACHED();
996    return E_NOTIMPL;
997}
998
999HRESULT STDMETHODCALLTYPE DOMElement::getElementsByTagNameNS(
1000        /* [in] */ BSTR /*namespaceURI*/,
1001        /* [in] */ BSTR /*localName*/,
1002        /* [retval][out] */ IDOMNodeList** /*result*/)
1003{
1004    ASSERT_NOT_REACHED();
1005    return E_NOTIMPL;
1006}
1007
1008HRESULT STDMETHODCALLTYPE DOMElement::hasAttribute(
1009        /* [in] */ BSTR /*name*/,
1010        /* [retval][out] */ BOOL* /*result*/)
1011{
1012    ASSERT_NOT_REACHED();
1013    return E_NOTIMPL;
1014}
1015
1016HRESULT STDMETHODCALLTYPE DOMElement::hasAttributeNS(
1017        /* [in] */ BSTR /*namespaceURI*/,
1018        /* [in] */ BSTR /*localName*/,
1019        /* [retval][out] */ BOOL* /*result*/)
1020{
1021    ASSERT_NOT_REACHED();
1022    return E_NOTIMPL;
1023}
1024
1025HRESULT STDMETHODCALLTYPE DOMElement::focus( void)
1026{
1027    if (!m_element)
1028        return E_FAIL;
1029    m_element->focus();
1030    return S_OK;
1031}
1032
1033HRESULT STDMETHODCALLTYPE DOMElement::blur( void)
1034{
1035    if (!m_element)
1036        return E_FAIL;
1037    m_element->blur();
1038    return S_OK;
1039}
1040
1041// IDOMElementPrivate ---------------------------------------------------------
1042
1043HRESULT DOMElement::coreElement(void **element)
1044{
1045    if (!m_element)
1046        return E_FAIL;
1047    *element = (void*) m_element;
1048    return S_OK;
1049}
1050
1051HRESULT STDMETHODCALLTYPE DOMElement::isEqual(
1052    /* [in] */ IDOMElement *other,
1053    /* [retval][out] */ BOOL *result)
1054{
1055    *result = FALSE;
1056
1057    if (!other || !result)
1058        return E_POINTER;
1059
1060    IDOMElementPrivate* otherPriv;
1061    HRESULT hr = other->QueryInterface(IID_IDOMElementPrivate, (void**) &otherPriv);
1062    if (FAILED(hr))
1063        return hr;
1064
1065    void* otherCoreEle;
1066    hr = otherPriv->coreElement(&otherCoreEle);
1067    otherPriv->Release();
1068    if (FAILED(hr))
1069        return hr;
1070
1071    *result = (otherCoreEle == (void*)m_element) ? TRUE : FALSE;
1072    return S_OK;
1073}
1074
1075HRESULT STDMETHODCALLTYPE DOMElement::isFocused(
1076    /* [retval][out] */ BOOL *result)
1077{
1078    if (!m_element)
1079        return E_FAIL;
1080
1081    if (m_element->document()->focusedNode() == m_element)
1082        *result = TRUE;
1083    else
1084        *result = FALSE;
1085
1086    return S_OK;
1087}
1088
1089HRESULT STDMETHODCALLTYPE DOMElement::innerText(
1090    /* [retval][out] */ BSTR* result)
1091{
1092    if (!result) {
1093        ASSERT_NOT_REACHED();
1094        return E_POINTER;
1095    }
1096
1097    if (!m_element) {
1098        ASSERT_NOT_REACHED();
1099        return E_FAIL;
1100    }
1101
1102    *result = BString(m_element->innerText()).release();
1103    return S_OK;
1104}
1105
1106HRESULT STDMETHODCALLTYPE DOMElement::font(WebFontDescription* webFontDescription)
1107{
1108    if (!webFontDescription) {
1109        ASSERT_NOT_REACHED();
1110        return E_POINTER;
1111    }
1112
1113    ASSERT(m_element);
1114
1115    WebCore::RenderObject* renderer = m_element->renderer();
1116    if (!renderer)
1117        return E_FAIL;
1118
1119    FontDescription fontDescription = renderer->style()->font().fontDescription();
1120    AtomicString family = fontDescription.family().family();
1121    webFontDescription->family = family.characters();
1122    webFontDescription->familyLength = family.length();
1123    webFontDescription->size = fontDescription.computedSize();
1124    webFontDescription->bold = fontDescription.weight() >= WebCore::FontWeight600;
1125    webFontDescription->italic = fontDescription.italic();
1126
1127    return S_OK;
1128}
1129
1130HRESULT STDMETHODCALLTYPE DOMElement::renderedImage(HBITMAP* image)
1131{
1132    if (!image) {
1133        ASSERT_NOT_REACHED();
1134        return E_POINTER;
1135    }
1136    *image = 0;
1137
1138    ASSERT(m_element);
1139
1140    Frame* frame = m_element->document()->frame();
1141    if (!frame)
1142        return E_FAIL;
1143
1144    *image = frame->nodeImage(m_element);
1145    if (!*image)
1146        return E_FAIL;
1147
1148    return S_OK;
1149}
1150
1151HRESULT STDMETHODCALLTYPE DOMElement::markerTextForListItem(
1152    /* [retval][out] */ BSTR* markerText)
1153{
1154    if (!markerText)
1155        return E_POINTER;
1156
1157    ASSERT(m_element);
1158
1159    *markerText = BString(WebCore::markerTextForListItem(m_element)).release();
1160    return S_OK;
1161}
1162
1163// IDOMElementCSSInlineStyle --------------------------------------------------
1164
1165HRESULT STDMETHODCALLTYPE DOMElement::style(
1166    /* [retval][out] */ IDOMCSSStyleDeclaration** result)
1167{
1168    if (!result)
1169        return E_POINTER;
1170    if (!m_element)
1171        return E_FAIL;
1172
1173    WebCore::CSSStyleDeclaration* style = m_element->style();
1174    if (!style)
1175        return E_FAIL;
1176
1177    *result = DOMCSSStyleDeclaration::createInstance(style);
1178    return *result ? S_OK : E_FAIL;
1179}
1180
1181// IDOMElementExtensions ------------------------------------------------------
1182
1183HRESULT STDMETHODCALLTYPE DOMElement::offsetLeft(
1184    /* [retval][out] */ int* result)
1185{
1186    if (!m_element)
1187        return E_FAIL;
1188
1189    *result = m_element->offsetLeft();
1190    return S_OK;
1191}
1192
1193HRESULT STDMETHODCALLTYPE DOMElement::offsetTop(
1194    /* [retval][out] */ int* result)
1195{
1196    if (!m_element)
1197        return E_FAIL;
1198
1199    *result = m_element->offsetTop();
1200    return S_OK;
1201}
1202
1203HRESULT STDMETHODCALLTYPE DOMElement::offsetWidth(
1204    /* [retval][out] */ int* result)
1205{
1206    if (!m_element)
1207        return E_FAIL;
1208
1209    *result = m_element->offsetWidth();
1210    return S_OK;
1211}
1212
1213HRESULT STDMETHODCALLTYPE DOMElement::offsetHeight(
1214    /* [retval][out] */ int* result)
1215{
1216    if (!m_element)
1217        return E_FAIL;
1218
1219    *result = m_element->offsetHeight();
1220    return S_OK;
1221}
1222
1223HRESULT STDMETHODCALLTYPE DOMElement::offsetParent(
1224    /* [retval][out] */ IDOMElement** /*result*/)
1225{
1226    // FIXME
1227    ASSERT_NOT_REACHED();
1228    return E_NOTIMPL;
1229}
1230
1231HRESULT STDMETHODCALLTYPE DOMElement::clientWidth(
1232    /* [retval][out] */ int* result)
1233{
1234    if (!m_element)
1235        return E_FAIL;
1236
1237    *result = m_element->clientWidth();
1238    return S_OK;
1239}
1240
1241HRESULT STDMETHODCALLTYPE DOMElement::clientHeight(
1242    /* [retval][out] */ int* result)
1243{
1244    if (!m_element)
1245        return E_FAIL;
1246
1247    *result = m_element->clientHeight();
1248    return S_OK;
1249}
1250
1251HRESULT STDMETHODCALLTYPE DOMElement::scrollLeft(
1252    /* [retval][out] */ int* result)
1253{
1254    if (!m_element)
1255        return E_FAIL;
1256
1257    *result = m_element->scrollLeft();
1258    return S_OK;
1259}
1260
1261HRESULT STDMETHODCALLTYPE DOMElement::setScrollLeft(
1262    /* [in] */ int /*newScrollLeft*/)
1263{
1264    // FIXME
1265    ASSERT_NOT_REACHED();
1266    return E_NOTIMPL;
1267}
1268
1269HRESULT STDMETHODCALLTYPE DOMElement::scrollTop(
1270    /* [retval][out] */ int* result)
1271{
1272    if (!m_element)
1273        return E_FAIL;
1274
1275    *result = m_element->scrollTop();
1276    return S_OK;
1277}
1278
1279HRESULT STDMETHODCALLTYPE DOMElement::setScrollTop(
1280    /* [in] */ int /*newScrollTop*/)
1281{
1282    // FIXME
1283    ASSERT_NOT_REACHED();
1284    return E_NOTIMPL;
1285}
1286
1287HRESULT STDMETHODCALLTYPE DOMElement::scrollWidth(
1288    /* [retval][out] */ int* result)
1289{
1290    if (!m_element)
1291        return E_FAIL;
1292
1293    *result = m_element->scrollWidth();
1294    return S_OK;
1295}
1296
1297HRESULT STDMETHODCALLTYPE DOMElement::scrollHeight(
1298    /* [retval][out] */ int* result)
1299{
1300    if (!m_element)
1301        return E_FAIL;
1302
1303    *result = m_element->scrollHeight();
1304    return S_OK;
1305}
1306
1307HRESULT STDMETHODCALLTYPE DOMElement::scrollIntoView(
1308    /* [in] */ BOOL alignWithTop)
1309{
1310    if (!m_element)
1311        return E_FAIL;
1312
1313    m_element->scrollIntoView(!!alignWithTop);
1314    return S_OK;
1315}
1316
1317HRESULT STDMETHODCALLTYPE DOMElement::scrollIntoViewIfNeeded(
1318    /* [in] */ BOOL centerIfNeeded)
1319{
1320    if (!m_element)
1321        return E_FAIL;
1322
1323    m_element->scrollIntoViewIfNeeded(!!centerIfNeeded);
1324    return S_OK;
1325}
1326
1327// DOMElement -----------------------------------------------------------------
1328
1329DOMElement::DOMElement(WebCore::Element* e)
1330: DOMNode(e)
1331, m_element(e)
1332{
1333}
1334
1335DOMElement::~DOMElement()
1336{
1337}
1338
1339IDOMElement* DOMElement::createInstance(WebCore::Element* e)
1340{
1341    if (!e)
1342        return 0;
1343
1344    HRESULT hr;
1345    IDOMElement* domElement = 0;
1346
1347    if (e->hasTagName(formTag)) {
1348        DOMHTMLFormElement* newElement = new DOMHTMLFormElement(e);
1349        hr = newElement->QueryInterface(IID_IDOMElement, (void**)&domElement);
1350    } else if (e->hasTagName(iframeTag)) {
1351        DOMHTMLIFrameElement* newElement = new DOMHTMLIFrameElement(e);
1352        hr = newElement->QueryInterface(IID_IDOMElement, (void**)&domElement);
1353    } else if (e->hasTagName(inputTag)) {
1354        DOMHTMLInputElement* newElement = new DOMHTMLInputElement(e);
1355        hr = newElement->QueryInterface(IID_IDOMElement, (void**)&domElement);
1356    } else if (e->hasTagName(optionTag)) {
1357        DOMHTMLOptionElement* newElement = new DOMHTMLOptionElement(e);
1358        hr = newElement->QueryInterface(IID_IDOMElement, (void**)&domElement);
1359    } else if (e->hasTagName(selectTag)) {
1360        DOMHTMLSelectElement* newElement = new DOMHTMLSelectElement(e);
1361        hr = newElement->QueryInterface(IID_IDOMElement, (void**)&domElement);
1362    } else if (e->hasTagName(textareaTag)) {
1363        DOMHTMLTextAreaElement* newElement = new DOMHTMLTextAreaElement(e);
1364        hr = newElement->QueryInterface(IID_IDOMElement, (void**)&domElement);
1365    } else if (e->isHTMLElement()) {
1366        DOMHTMLElement* newElement = new DOMHTMLElement(e);
1367        hr = newElement->QueryInterface(IID_IDOMElement, (void**)&domElement);
1368    } else {
1369        DOMElement* newElement = new DOMElement(e);
1370        hr = newElement->QueryInterface(IID_IDOMElement, (void**)&domElement);
1371    }
1372
1373    if (FAILED(hr))
1374        return 0;
1375
1376    return domElement;
1377}
1378