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 "WebHTMLRepresentation.h"
29
30#include "WebKit.h"
31#include "WebFrame.h"
32#include "WebKitStatisticsPrivate.h"
33#include <WebCore/BString.h>
34#include <WebCore/Frame.h>
35#include <WebCore/HTMLInputElement.h>
36#include <WebCore/TextResourceDecoder.h>
37
38using namespace WebCore;
39
40// WebHTMLRepresentation ------------------------------------------------------
41
42WebHTMLRepresentation::WebHTMLRepresentation()
43    : m_refCount(0)
44    , m_frame(0)
45{
46    WebHTMLRepresentationCount++;
47    gClassCount++;
48    gClassNameCount.add("WebHTMLRepresentation");
49}
50
51WebHTMLRepresentation::~WebHTMLRepresentation()
52{
53    if (m_frame) {
54        m_frame->Release();
55        m_frame = 0;
56    }
57
58    WebHTMLRepresentationCount--;
59    gClassCount--;
60    gClassNameCount.remove("WebHTMLRepresentation");
61}
62
63WebHTMLRepresentation* WebHTMLRepresentation::createInstance(WebFrame* frame)
64{
65    WebHTMLRepresentation* instance = new WebHTMLRepresentation();
66    instance->m_frame = frame;
67    frame->AddRef();
68    instance->AddRef();
69    return instance;
70}
71
72// IUnknown -------------------------------------------------------------------
73
74HRESULT STDMETHODCALLTYPE WebHTMLRepresentation::QueryInterface(REFIID riid, void** ppvObject)
75{
76    *ppvObject = 0;
77    if (IsEqualGUID(riid, IID_IUnknown))
78        *ppvObject = static_cast<IWebHTMLRepresentation*>(this);
79    else if (IsEqualGUID(riid, IID_IWebHTMLRepresentation))
80        *ppvObject = static_cast<IWebHTMLRepresentation*>(this);
81    else if (IsEqualGUID(riid, IID_IWebDocumentRepresentation))
82        *ppvObject = static_cast<IWebDocumentRepresentation*>(this);
83    else
84        return E_NOINTERFACE;
85
86    AddRef();
87    return S_OK;
88}
89
90ULONG STDMETHODCALLTYPE WebHTMLRepresentation::AddRef()
91{
92    return ++m_refCount;
93}
94
95ULONG STDMETHODCALLTYPE WebHTMLRepresentation::Release()
96{
97    ULONG newRef = --m_refCount;
98    if (!newRef)
99        delete(this);
100
101    return newRef;
102}
103
104// IWebHTMLRepresentation --------------------------------------------------------------------
105
106HRESULT STDMETHODCALLTYPE WebHTMLRepresentation::supportedMIMETypes(
107        /* [out][in] */ BSTR* /*types*/,
108        /* [out][in] */ int* /*cTypes*/)
109{
110    ASSERT_NOT_REACHED();
111    return E_NOTIMPL;
112}
113
114HRESULT STDMETHODCALLTYPE WebHTMLRepresentation::supportedNonImageMIMETypes(
115        /* [out][in] */ BSTR* /*types*/,
116        /* [out][in] */ int* /*cTypes*/)
117{
118    ASSERT_NOT_REACHED();
119    return E_NOTIMPL;
120}
121
122HRESULT STDMETHODCALLTYPE WebHTMLRepresentation::supportedImageMIMETypes(
123        /* [out][in] */ BSTR* /*types*/,
124        /* [out][in] */ int* /*cTypes*/)
125{
126    ASSERT_NOT_REACHED();
127    return E_NOTIMPL;
128}
129
130HRESULT STDMETHODCALLTYPE WebHTMLRepresentation::attributedStringFromDOMNodes(
131        /* [in] */ IDOMNode* /*startNode*/,
132        /* [in] */ int /*startOffset*/,
133        /* [in] */ IDOMNode* /*endNode*/,
134        /* [in] */ int /*endOffset*/,
135        /* [retval][out] */ IDataObject** /*attributedString*/)
136{
137    ASSERT_NOT_REACHED();
138    return E_NOTIMPL;
139}
140
141HRESULT STDMETHODCALLTYPE WebHTMLRepresentation::elementWithName(
142        /* [in] */ BSTR name,
143        /* [in] */ IDOMElement* form,
144        /* [retval][out] */ IDOMElement** element)
145{
146    if (!m_frame)
147        return E_FAIL;
148
149    return m_frame->elementWithName(name, form, element);
150}
151
152HRESULT STDMETHODCALLTYPE WebHTMLRepresentation::elementDoesAutoComplete(
153        /* [in] */ IDOMElement* element,
154        /* [retval][out] */ BOOL* result)
155{
156    BOOL doesAutoComplete;
157    HRESULT hr = m_frame->elementDoesAutoComplete(element, &doesAutoComplete);
158    *result = doesAutoComplete ? TRUE : FALSE;
159    return hr;
160}
161
162HRESULT STDMETHODCALLTYPE WebHTMLRepresentation::elementIsPassword(
163        /* [in] */ IDOMElement* element,
164        /* [retval][out] */ BOOL* result)
165{
166    bool isPassword;
167    HRESULT hr = m_frame->elementIsPassword(element, &isPassword);
168    *result = isPassword ?  TRUE : FALSE;
169    return hr;
170}
171
172HRESULT STDMETHODCALLTYPE WebHTMLRepresentation::formForElement(
173        /* [in] */ IDOMElement* element,
174        /* [retval][out] */ IDOMElement** form)
175{
176    if (!m_frame)
177        return E_FAIL;
178
179    return m_frame->formForElement(element, form);
180}
181
182HRESULT STDMETHODCALLTYPE WebHTMLRepresentation::currentForm(
183        /* [retval][out] */ IDOMElement** form)
184{
185    if (!m_frame)
186        return E_FAIL;
187
188    return m_frame->currentForm(form);
189}
190
191HRESULT STDMETHODCALLTYPE WebHTMLRepresentation::controlsInForm(
192        /* [in] */ IDOMElement* form,
193        /* [out][in] */ IDOMElement** controls,
194        /* [out][in] */ int* cControls)
195{
196    return m_frame->controlsInForm(form, controls, cControls);
197}
198
199HRESULT STDMETHODCALLTYPE WebHTMLRepresentation::deprecatedSearchForLabels(
200        /* [size_is][in] */ BSTR* labels,
201        /* [in] */ int cLabels,
202        /* [in] */ IDOMElement* beforeElement,
203        /* [retval][out] */ BSTR* result)
204{
205    return m_frame->searchForLabelsBeforeElement(labels, cLabels, beforeElement, 0, 0, result);
206}
207
208HRESULT STDMETHODCALLTYPE WebHTMLRepresentation::matchLabels(
209        /* [size_is][in] */ BSTR* labels,
210        /* [in] */ int cLabels,
211        /* [in] */ IDOMElement* againstElement,
212        /* [retval][out] */ BSTR* result)
213{
214    return m_frame->matchLabelsAgainstElement(labels, cLabels, againstElement, result);
215}
216
217HRESULT WebHTMLRepresentation::searchForLabels(BSTR* labels, unsigned cLabels, IDOMElement* beforeElement, unsigned* resultDistance, BOOL* resultIsInCellAbove, BSTR* result)
218{
219    return m_frame->searchForLabelsBeforeElement(labels, cLabels, beforeElement, resultDistance, resultIsInCellAbove, result);
220}
221
222// IWebDocumentRepresentation ----------------------------------------------------------------
223
224HRESULT STDMETHODCALLTYPE WebHTMLRepresentation::setDataSource(
225        /* [in] */ IWebDataSource* /*dataSource*/)
226{
227    ASSERT_NOT_REACHED();
228    return E_NOTIMPL;
229}
230
231HRESULT STDMETHODCALLTYPE WebHTMLRepresentation::receivedData(
232        /* [in] */ IStream* /*data*/,
233        /* [in] */ IWebDataSource* /*dataSource*/)
234{
235    ASSERT_NOT_REACHED();
236    return E_NOTIMPL;
237}
238
239HRESULT STDMETHODCALLTYPE WebHTMLRepresentation::receivedError(
240        /* [in] */ IWebError* /*error*/,
241        /* [in] */ IWebDataSource* /*dataSource*/)
242{
243    ASSERT_NOT_REACHED();
244    return E_NOTIMPL;
245}
246
247HRESULT STDMETHODCALLTYPE WebHTMLRepresentation::finishedLoadingWithDataSource(
248        /* [in] */ IWebDataSource* /*dataSource*/)
249{
250    ASSERT_NOT_REACHED();
251    return E_NOTIMPL;
252}
253
254HRESULT STDMETHODCALLTYPE WebHTMLRepresentation::canProvideDocumentSource(
255        /* [retval][out] */ BOOL* result)
256{
257    bool canProvideSource;
258    HRESULT hr = this->m_frame->canProvideDocumentSource(&canProvideSource);
259    *result = canProvideSource ? TRUE : FALSE;
260    return hr;
261}
262
263HRESULT STDMETHODCALLTYPE WebHTMLRepresentation::documentSource(
264        /* [retval][out] */ BSTR* source)
265{
266    if (!source)
267        return E_FAIL;
268
269    *source = 0;
270
271    HRESULT hr = S_OK;
272
273    COMPtr<IWebDataSource> dataSource;
274    hr = m_frame->dataSource(&dataSource);
275    if (FAILED(hr))
276        return hr;
277
278    COMPtr<IStream> data;
279    hr = dataSource->data(&data);
280    if (FAILED(hr))
281        return hr;
282
283    STATSTG stat;
284    hr = data->Stat(&stat, STATFLAG_NONAME);
285    if (FAILED(hr))
286        return hr;
287
288    if (stat.cbSize.HighPart || !stat.cbSize.LowPart)
289        return E_FAIL;
290
291    Vector<char> dataBuffer(stat.cbSize.LowPart);
292    ULONG read;
293
294    hr = data->Read(dataBuffer.data(), static_cast<ULONG>(dataBuffer.size()), &read);
295    if (FAILED(hr))
296        return hr;
297
298    WebCore::Frame* frame = core(m_frame);
299    if (!frame)
300        return E_FAIL;
301
302    WebCore::Document* doc = frame->document();
303    if (!doc)
304        return E_FAIL;
305
306    WebCore::TextResourceDecoder* decoder = doc->decoder();
307    if (!decoder)
308        return E_FAIL;
309
310    *source = WebCore::BString(decoder->encoding().decode(dataBuffer.data(), dataBuffer.size())).release();
311    return S_OK;
312}
313
314HRESULT STDMETHODCALLTYPE WebHTMLRepresentation::title(
315        /* [retval][out] */ BSTR* /*docTitle*/)
316{
317    ASSERT_NOT_REACHED();
318    return E_NOTIMPL;
319}
320