1 /*
2 * Copyright (C) 2006, 2007 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 "WebElementPropertyBag.h"
29
30 #include "MarshallingHelpers.h"
31 #include "DOMCoreClasses.h"
32 #include "WebFrame.h"
33 #include <WebCore/Document.h>
34 #include <WebCore/Frame.h>
35 #include <WebCore/HitTestResult.h>
36 #include <WebCore/FrameLoader.h>
37 #include <WebCore/Image.h>
38 #include <WebCore/KURL.h>
39 #include <WebCore/RenderObject.h>
40
41 using namespace WebCore;
42
43 // WebElementPropertyBag -----------------------------------------------
WebElementPropertyBag(const HitTestResult & result)44 WebElementPropertyBag::WebElementPropertyBag(const HitTestResult& result)
45 : m_result(new HitTestResult(result))
46 , m_refCount(0)
47 {
48 gClassCount++;
49 gClassNameCount.add("WebElementPropertyBag");
50 }
51
~WebElementPropertyBag()52 WebElementPropertyBag::~WebElementPropertyBag()
53 {
54 gClassCount--;
55 gClassNameCount.remove("WebElementPropertyBag");
56 }
57
createInstance(const HitTestResult & result)58 WebElementPropertyBag* WebElementPropertyBag::createInstance(const HitTestResult& result)
59 {
60 WebElementPropertyBag* instance = new WebElementPropertyBag(result);
61 instance->AddRef();
62
63 return instance;
64 }
65
66 // IUnknown -------------------------------------------------------------------
67
QueryInterface(REFIID riid,void ** ppvObject)68 HRESULT STDMETHODCALLTYPE WebElementPropertyBag::QueryInterface(REFIID riid, void** ppvObject)
69 {
70 *ppvObject = 0;
71 if (IsEqualGUID(riid, IID_IUnknown))
72 *ppvObject = static_cast<IPropertyBag*>(this);
73 else if (IsEqualGUID(riid, IID_IPropertyBag))
74 *ppvObject = static_cast<IPropertyBag*>(this);
75 else
76 return E_NOINTERFACE;
77
78 AddRef();
79 return S_OK;
80 }
81
AddRef(void)82 ULONG STDMETHODCALLTYPE WebElementPropertyBag::AddRef(void)
83 {
84 return ++m_refCount;
85 }
86
Release(void)87 ULONG STDMETHODCALLTYPE WebElementPropertyBag::Release(void)
88 {
89 ULONG newRef = --m_refCount;
90 if (!newRef)
91 delete this;
92
93 return newRef;
94 }
95
isEqual(LPCWSTR s1,LPCWSTR s2)96 static bool isEqual(LPCWSTR s1, LPCWSTR s2)
97 {
98 return !wcscmp(s1, s2);
99 }
100
convertStringToVariant(VARIANT * pVar,const String & string)101 static HRESULT convertStringToVariant(VARIANT* pVar, const String& string)
102 {
103 V_VT(pVar) = VT_BSTR;
104 V_BSTR(pVar) = SysAllocStringLen(string.characters(), string.length());
105 if (string.length() && !V_BSTR(pVar))
106 return E_OUTOFMEMORY;
107
108 return S_OK;
109 }
110
111
Read(LPCOLESTR pszPropName,VARIANT * pVar,IErrorLog *)112 HRESULT STDMETHODCALLTYPE WebElementPropertyBag::Read(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog * /*pErrorLog*/)
113 {
114 if (!pszPropName)
115 return E_POINTER;
116
117 if (!m_result)
118 return E_FAIL;
119
120 BSTR key = (BSTR)pszPropName;
121 VariantClear(pVar);
122 if (isEqual(WebElementDOMNodeKey, key)) {
123 IDOMNode* node = DOMNode::createInstance(m_result->innerNonSharedNode());
124 V_VT(pVar) = VT_UNKNOWN;
125 V_UNKNOWN(pVar) = node;
126 return S_OK;
127 } else if (isEqual(WebElementFrameKey, key)) {
128 if (!(m_result->innerNonSharedNode() && m_result->innerNonSharedNode()->document()
129 && m_result->innerNonSharedNode()->document()->frame()))
130 return E_FAIL;
131 Frame* coreFrame = m_result->innerNonSharedNode()->document()->frame();
132 WebFrame* webFrame = static_cast<WebFrame*>(coreFrame->loader()->client());
133 IWebFrame* iWebFrame;
134 if (FAILED(webFrame->QueryInterface(IID_IWebFrame, (void**)&iWebFrame)))
135 return E_FAIL;
136 V_VT(pVar) = VT_UNKNOWN;
137 V_UNKNOWN(pVar) = iWebFrame;
138 return S_OK;
139 } else if (isEqual(WebElementImageAltStringKey, key))
140 return convertStringToVariant(pVar, m_result->altDisplayString());
141 else if (isEqual(WebElementImageKey, key)) {
142 V_VT(pVar) = VT_BYREF;
143 V_BYREF(pVar) = m_result->image();
144 return S_OK;
145 } else if (isEqual(WebElementImageRectKey, key)) {
146 V_VT(pVar) = VT_ARRAY;
147 IntRect boundingBox = m_result->innerNonSharedNode() && m_result->innerNonSharedNode()->renderer() ?
148 m_result->innerNonSharedNode()->renderer()->absoluteBoundingBoxRect(true) : IntRect();
149 V_ARRAY(pVar) = MarshallingHelpers::intRectToSafeArray(boundingBox);
150 return S_OK;
151 } else if (isEqual(WebElementImageURLKey, key))
152 return convertStringToVariant(pVar, m_result->absoluteImageURL().string());
153 else if (isEqual(WebElementIsSelectedKey, key)) {
154 V_VT(pVar) = VT_BOOL;
155 if (m_result->isSelected())
156 V_BOOL(pVar) = VARIANT_TRUE;
157 else
158 V_BOOL(pVar) = VARIANT_FALSE;
159 return S_OK;
160 }
161 if (isEqual(WebElementMediaURLKey, key))
162 return convertStringToVariant(pVar, m_result->absoluteMediaURL().string());
163 if (isEqual(WebElementSpellingToolTipKey, key)) {
164 TextDirection dir;
165 return convertStringToVariant(pVar, m_result->spellingToolTip(dir));
166 } else if (isEqual(WebElementTitleKey, key)) {
167 TextDirection dir;
168 return convertStringToVariant(pVar, m_result->title(dir));
169 }
170 else if (isEqual(WebElementLinkURLKey, key))
171 return convertStringToVariant(pVar, m_result->absoluteLinkURL().string());
172 else if (isEqual(WebElementLinkTargetFrameKey, key)) {
173 if (!m_result->targetFrame())
174 return E_FAIL;
175 WebFrame* webFrame = kit(m_result->targetFrame());
176 IWebFrame* iWebFrame;
177 if (FAILED(webFrame->QueryInterface(IID_IWebFrame, (void**)&iWebFrame)))
178 return E_FAIL;
179 V_VT(pVar) = VT_UNKNOWN;
180 V_UNKNOWN(pVar) = iWebFrame;
181 return S_OK;
182 } else if (isEqual(WebElementLinkTitleKey, key))
183 return convertStringToVariant(pVar, m_result->titleDisplayString());
184 else if (isEqual(WebElementLinkLabelKey, key))
185 return convertStringToVariant(pVar, m_result->textContent());
186 else if (isEqual(WebElementIsContentEditableKey, key)) {
187 V_VT(pVar) = VT_BOOL;
188 if (m_result->isContentEditable())
189 V_BOOL(pVar) = VARIANT_TRUE;
190 else
191 V_BOOL(pVar) = VARIANT_FALSE;
192 return S_OK;
193 }
194
195 return E_INVALIDARG;
196 }
197
Write(LPCOLESTR pszPropName,VARIANT * pVar)198 HRESULT STDMETHODCALLTYPE WebElementPropertyBag::Write(LPCOLESTR pszPropName, VARIANT* pVar)
199 {
200 if (!pszPropName || !pVar)
201 return E_POINTER;
202
203 return E_FAIL;
204 }
205