1/*
2 * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "InjectedBundleNodeHandle.h"
28
29#include "WebFrame.h"
30#include "WebFrameLoaderClient.h"
31#include <JavaScriptCore/APICast.h>
32#include <WebCore/Document.h>
33#include <WebCore/Frame.h>
34#include <WebCore/HTMLFrameElement.h>
35#include <WebCore/HTMLIFrameElement.h>
36#include <WebCore/HTMLInputElement.h>
37#include <WebCore/HTMLNames.h>
38#include <WebCore/HTMLTableCellElement.h>
39#include <WebCore/HTMLTextAreaElement.h>
40#include <WebCore/IntRect.h>
41#include <WebCore/JSNode.h>
42#include <WebCore/Node.h>
43#include <wtf/HashMap.h>
44#include <wtf/text/WTFString.h>
45
46using namespace WebCore;
47using namespace HTMLNames;
48
49namespace WebKit {
50
51typedef HashMap<Node*, InjectedBundleNodeHandle*> DOMHandleCache;
52
53static DOMHandleCache& domHandleCache()
54{
55    DEFINE_STATIC_LOCAL(DOMHandleCache, cache, ());
56    return cache;
57}
58
59PassRefPtr<InjectedBundleNodeHandle> InjectedBundleNodeHandle::getOrCreate(JSContextRef, JSObjectRef object)
60{
61    Node* node = toNode(toJS(object));
62    return getOrCreate(node);
63}
64
65PassRefPtr<InjectedBundleNodeHandle> InjectedBundleNodeHandle::getOrCreate(Node* node)
66{
67    if (!node)
68        return 0;
69
70    std::pair<DOMHandleCache::iterator, bool> result = domHandleCache().add(node, 0);
71    if (!result.second)
72        return PassRefPtr<InjectedBundleNodeHandle>(result.first->second);
73
74    RefPtr<InjectedBundleNodeHandle> nodeHandle = InjectedBundleNodeHandle::create(node);
75    result.first->second = nodeHandle.get();
76    return nodeHandle.release();
77}
78
79PassRefPtr<InjectedBundleNodeHandle> InjectedBundleNodeHandle::create(Node* node)
80{
81    return adoptRef(new InjectedBundleNodeHandle(node));
82}
83
84InjectedBundleNodeHandle::InjectedBundleNodeHandle(Node* node)
85    : m_node(node)
86{
87}
88
89InjectedBundleNodeHandle::~InjectedBundleNodeHandle()
90{
91    domHandleCache().remove(m_node.get());
92}
93
94Node* InjectedBundleNodeHandle::coreNode() const
95{
96    return m_node.get();
97}
98
99PassRefPtr<InjectedBundleNodeHandle> InjectedBundleNodeHandle::document()
100{
101    return getOrCreate(m_node->document());
102}
103
104// Additional DOM Operations
105// Note: These should only be operations that are not exposed to JavaScript.
106
107IntRect InjectedBundleNodeHandle::elementBounds() const
108{
109    if (!m_node->isElementNode())
110        return IntRect();
111
112    return static_cast<Element*>(m_node.get())->boundsInWindowSpace();
113}
114
115IntRect InjectedBundleNodeHandle::renderRect(bool* isReplaced) const
116{
117    return m_node.get()->renderRect(isReplaced);
118}
119
120void InjectedBundleNodeHandle::setHTMLInputElementValueForUser(const String& value)
121{
122    if (!m_node->hasTagName(inputTag))
123        return;
124
125    static_cast<HTMLInputElement*>(m_node.get())->setValueForUser(value);
126}
127
128bool InjectedBundleNodeHandle::isHTMLInputElementAutofilled() const
129{
130    if (!m_node->hasTagName(inputTag))
131        return false;
132
133    return static_cast<HTMLInputElement*>(m_node.get())->isAutofilled();
134}
135
136void InjectedBundleNodeHandle::setHTMLInputElementAutofilled(bool filled)
137{
138    if (!m_node->hasTagName(inputTag))
139        return;
140
141    static_cast<HTMLInputElement*>(m_node.get())->setAutofilled(filled);
142}
143
144bool InjectedBundleNodeHandle::htmlInputElementLastChangeWasUserEdit()
145{
146    if (!m_node->hasTagName(inputTag))
147        return false;
148
149    return static_cast<HTMLInputElement*>(m_node.get())->lastChangeWasUserEdit();
150}
151
152bool InjectedBundleNodeHandle::htmlTextAreaElementLastChangeWasUserEdit()
153{
154    if (!m_node->hasTagName(textareaTag))
155        return false;
156
157    return static_cast<HTMLTextAreaElement*>(m_node.get())->lastChangeWasUserEdit();
158}
159
160PassRefPtr<InjectedBundleNodeHandle> InjectedBundleNodeHandle::htmlTableCellElementCellAbove()
161{
162    if (!m_node->hasTagName(tdTag))
163        return 0;
164
165    return getOrCreate(static_cast<HTMLTableCellElement*>(m_node.get())->cellAbove());
166}
167
168PassRefPtr<InjectedBundleNodeHandle> InjectedBundleNodeHandle::elementShadowRoot()
169{
170    if (!m_node->isElementNode())
171        return 0;
172
173    return getOrCreate(static_cast<Element*>(m_node.get())->shadowRoot());
174}
175
176PassRefPtr<WebFrame> InjectedBundleNodeHandle::documentFrame()
177{
178    if (!m_node->isDocumentNode())
179        return 0;
180
181    Frame* frame = static_cast<Document*>(m_node.get())->frame();
182    if (!frame)
183        return 0;
184
185    return static_cast<WebFrameLoaderClient*>(frame->loader()->client())->webFrame();
186}
187
188PassRefPtr<WebFrame> InjectedBundleNodeHandle::htmlFrameElementContentFrame()
189{
190    if (!m_node->hasTagName(frameTag))
191        return 0;
192
193    Frame* frame = static_cast<HTMLFrameElement*>(m_node.get())->contentFrame();
194    if (!frame)
195        return 0;
196
197    return static_cast<WebFrameLoaderClient*>(frame->loader()->client())->webFrame();
198}
199
200PassRefPtr<WebFrame> InjectedBundleNodeHandle::htmlIFrameElementContentFrame()
201{
202    if (!m_node->hasTagName(iframeTag))
203        return 0;
204
205    Frame* frame = static_cast<HTMLIFrameElement*>(m_node.get())->contentFrame();
206    if (!frame)
207        return 0;
208
209    return static_cast<WebFrameLoaderClient*>(frame->loader()->client())->webFrame();
210}
211
212} // namespace WebKit
213