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