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 41using namespace WebCore; 42 43// WebElementPropertyBag ----------------------------------------------- 44WebElementPropertyBag::WebElementPropertyBag(const HitTestResult& result) 45 : m_result(new HitTestResult(result)) 46 , m_refCount(0) 47{ 48 gClassCount++; 49 gClassNameCount.add("WebElementPropertyBag"); 50} 51 52WebElementPropertyBag::~WebElementPropertyBag() 53{ 54 gClassCount--; 55 gClassNameCount.remove("WebElementPropertyBag"); 56} 57 58WebElementPropertyBag* WebElementPropertyBag::createInstance(const HitTestResult& result) 59{ 60 WebElementPropertyBag* instance = new WebElementPropertyBag(result); 61 instance->AddRef(); 62 63 return instance; 64} 65 66// IUnknown ------------------------------------------------------------------- 67 68HRESULT 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 82ULONG STDMETHODCALLTYPE WebElementPropertyBag::AddRef(void) 83{ 84 return ++m_refCount; 85} 86 87ULONG STDMETHODCALLTYPE WebElementPropertyBag::Release(void) 88{ 89 ULONG newRef = --m_refCount; 90 if (!newRef) 91 delete this; 92 93 return newRef; 94} 95 96static bool isEqual(LPCWSTR s1, LPCWSTR s2) 97{ 98 return !wcscmp(s1, s2); 99} 100 101static 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 112HRESULT 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 198HRESULT STDMETHODCALLTYPE WebElementPropertyBag::Write(LPCOLESTR pszPropName, VARIANT* pVar) 199{ 200 if (!pszPropName || !pVar) 201 return E_POINTER; 202 203 return E_FAIL; 204} 205