1/* 2 * Copyright (C) 2006, 2007, 2013 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. ``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 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 "WebFrameLoaderClient.h" 34#include <WebCore/BString.h> 35#include <WebCore/Document.h> 36#include <WebCore/Frame.h> 37#include <WebCore/HitTestResult.h> 38#include <WebCore/FrameLoader.h> 39#include <WebCore/Image.h> 40#include <WebCore/URL.h> 41#include <WebCore/RenderObject.h> 42 43using namespace WebCore; 44 45// WebElementPropertyBag ----------------------------------------------- 46WebElementPropertyBag::WebElementPropertyBag(const HitTestResult& result) 47 : m_result(adoptPtr(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) = BString(string).release(); 107 if (string.length() && !V_BSTR(pVar)) 108 return E_OUTOFMEMORY; 109 110 return S_OK; 111} 112 113 114HRESULT 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().frame())) 131 return E_FAIL; 132 Frame* coreFrame = m_result->innerNonSharedNode()->document().frame(); 133 WebFrame* webFrame = static_cast<WebFrameLoaderClient&>(coreFrame->loader().client()).webFrame(); 134 IWebFrame* iWebFrame; 135 if (FAILED(webFrame->QueryInterface(IID_IWebFrame, (void**)&iWebFrame))) 136 return E_FAIL; 137 V_VT(pVar) = VT_UNKNOWN; 138 V_UNKNOWN(pVar) = iWebFrame; 139 return S_OK; 140 } else if (isEqual(WebElementImageAltStringKey, key)) 141 return convertStringToVariant(pVar, m_result->altDisplayString()); 142 else if (isEqual(WebElementImageKey, key)) { 143 V_VT(pVar) = VT_BYREF; 144 V_BYREF(pVar) = m_result->image(); 145 return S_OK; 146 } else if (isEqual(WebElementImageRectKey, key)) { 147 V_VT(pVar) = VT_ARRAY; 148 IntRect boundingBox = m_result->innerNonSharedNode() && m_result->innerNonSharedNode()->renderer() ? 149 m_result->innerNonSharedNode()->renderer()->absoluteBoundingBoxRect(true) : IntRect(); 150 V_ARRAY(pVar) = MarshallingHelpers::intRectToSafeArray(boundingBox); 151 return S_OK; 152 } else if (isEqual(WebElementImageURLKey, key)) 153 return convertStringToVariant(pVar, m_result->absoluteImageURL().string()); 154 else if (isEqual(WebElementIsSelectedKey, key)) { 155 V_VT(pVar) = VT_BOOL; 156 if (m_result->isSelected()) 157 V_BOOL(pVar) = VARIANT_TRUE; 158 else 159 V_BOOL(pVar) = VARIANT_FALSE; 160 return S_OK; 161 } 162 if (isEqual(WebElementMediaURLKey, key)) 163 return convertStringToVariant(pVar, m_result->absoluteMediaURL().string()); 164 if (isEqual(WebElementSpellingToolTipKey, key)) { 165 TextDirection dir; 166 return convertStringToVariant(pVar, m_result->spellingToolTip(dir)); 167 } else if (isEqual(WebElementTitleKey, key)) { 168 TextDirection dir; 169 return convertStringToVariant(pVar, m_result->title(dir)); 170 } 171 else if (isEqual(WebElementLinkURLKey, key)) 172 return convertStringToVariant(pVar, m_result->absoluteLinkURL().string()); 173 else if (isEqual(WebElementLinkTargetFrameKey, key)) { 174 if (!m_result->targetFrame()) 175 return E_FAIL; 176 WebFrame* webFrame = kit(m_result->targetFrame()); 177 IWebFrame* iWebFrame; 178 if (FAILED(webFrame->QueryInterface(IID_IWebFrame, (void**)&iWebFrame))) 179 return E_FAIL; 180 V_VT(pVar) = VT_UNKNOWN; 181 V_UNKNOWN(pVar) = iWebFrame; 182 return S_OK; 183 } else if (isEqual(WebElementLinkTitleKey, key)) 184 return convertStringToVariant(pVar, m_result->titleDisplayString()); 185 else if (isEqual(WebElementLinkLabelKey, key)) 186 return convertStringToVariant(pVar, m_result->textContent()); 187 else if (isEqual(WebElementIsContentEditableKey, key)) { 188 V_VT(pVar) = VT_BOOL; 189 if (m_result->isContentEditable()) 190 V_BOOL(pVar) = VARIANT_TRUE; 191 else 192 V_BOOL(pVar) = VARIANT_FALSE; 193 return S_OK; 194 } 195 196 return E_INVALIDARG; 197} 198 199HRESULT STDMETHODCALLTYPE WebElementPropertyBag::Write(LPCOLESTR pszPropName, VARIANT* pVar) 200{ 201 if (!pszPropName || !pVar) 202 return E_POINTER; 203 204 return E_FAIL; 205} 206