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 "WebDataSource.h"
29
30#include "WebKit.h"
31#include "MemoryStream.h"
32#include "WebDocumentLoader.h"
33#include "WebError.h"
34#include "WebFrame.h"
35#include "WebKit.h"
36#include "WebHTMLRepresentation.h"
37#include "WebKitStatisticsPrivate.h"
38#include "WebMutableURLRequest.h"
39#include "WebResource.h"
40#include "WebURLResponse.h"
41#include <WebCore/BString.h>
42#include <WebCore/DocLoader.h>
43#include <WebCore/Document.h>
44#include <WebCore/Frame.h>
45#include <WebCore/FrameLoader.h>
46#include <WebCore/KURL.h>
47
48using namespace WebCore;
49
50// WebDataSource ----------------------------------------------------------------
51
52// {F230854D-7091-428a-8DB5-37CABA44C105}
53const GUID IID_WebDataSource =
54{ 0x5c2f9099, 0xe65e, 0x4a0f, { 0x9c, 0xa0, 0x6a, 0xd6, 0x92, 0x52, 0xa6, 0x2a } };
55
56WebDataSource::WebDataSource(WebDocumentLoader* loader)
57    : m_refCount(0)
58    , m_loader(loader)
59{
60    WebDataSourceCount++;
61    gClassCount++;
62    gClassNameCount.add("WebDataSource");
63}
64
65WebDataSource::~WebDataSource()
66{
67    if (m_loader)
68        m_loader->detachDataSource();
69    WebDataSourceCount--;
70    gClassCount--;
71    gClassNameCount.remove("WebDataSource");
72}
73
74WebDataSource* WebDataSource::createInstance(WebDocumentLoader* loader)
75{
76    WebDataSource* instance = new WebDataSource(loader);
77    instance->AddRef();
78    return instance;
79}
80
81WebDocumentLoader* WebDataSource::documentLoader() const
82{
83    return m_loader.get();
84}
85
86// IWebDataSourcePrivate ------------------------------------------------------
87
88HRESULT STDMETHODCALLTYPE WebDataSource::overrideEncoding(
89    /* [retval][out] */ BSTR* /*encoding*/)
90{
91    ASSERT_NOT_REACHED();
92    return E_NOTIMPL;
93}
94
95HRESULT STDMETHODCALLTYPE WebDataSource::setOverrideEncoding(
96    /* [in] */ BSTR /*encoding*/)
97{
98    ASSERT_NOT_REACHED();
99    return E_NOTIMPL;
100}
101
102HRESULT STDMETHODCALLTYPE WebDataSource::mainDocumentError(
103        /* [retval][out] */ IWebError** error)
104{
105    if (!error) {
106        ASSERT_NOT_REACHED();
107        return E_POINTER;
108    }
109
110    *error = 0;
111
112    if (!m_loader)
113        return E_FAIL;
114
115    if (m_loader->mainDocumentError().isNull())
116        return S_OK;
117
118    *error = WebError::createInstance(m_loader->mainDocumentError());
119    return S_OK;
120}
121
122// IUnknown -------------------------------------------------------------------
123
124HRESULT STDMETHODCALLTYPE WebDataSource::QueryInterface(REFIID riid, void** ppvObject)
125{
126    *ppvObject = 0;
127    if (IsEqualGUID(riid, IID_WebDataSource))
128        *ppvObject = this;
129    else if (IsEqualGUID(riid, IID_IUnknown))
130        *ppvObject = static_cast<IWebDataSource*>(this);
131    else if (IsEqualGUID(riid, IID_IWebDataSource))
132        *ppvObject = static_cast<IWebDataSource*>(this);
133    else if (IsEqualGUID(riid, IID_IWebDataSourcePrivate))
134        *ppvObject = static_cast<IWebDataSourcePrivate*>(this);
135    else
136        return E_NOINTERFACE;
137
138    AddRef();
139    return S_OK;
140}
141
142ULONG STDMETHODCALLTYPE WebDataSource::AddRef(void)
143{
144    return ++m_refCount;
145}
146
147ULONG STDMETHODCALLTYPE WebDataSource::Release(void)
148{
149    ULONG newRef = --m_refCount;
150    if (!newRef)
151        delete(this);
152
153    return newRef;
154}
155
156// IWebDataSource --------------------------------------------------------------
157
158HRESULT STDMETHODCALLTYPE WebDataSource::initWithRequest(
159    /* [in] */ IWebURLRequest* /*request*/)
160{
161    ASSERT_NOT_REACHED();
162    return E_NOTIMPL;
163}
164
165HRESULT STDMETHODCALLTYPE WebDataSource::data(
166    /* [retval][out] */ IStream** stream)
167{
168    *stream = 0;
169    if (!m_loader)
170        return E_FAIL;
171
172    return MemoryStream::createInstance(m_loader->mainResourceData()).copyRefTo(stream);
173}
174
175HRESULT STDMETHODCALLTYPE WebDataSource::representation(
176    /* [retval][out] */ IWebDocumentRepresentation** rep)
177{
178    HRESULT hr = S_OK;
179    if (!m_representation) {
180        WebHTMLRepresentation* htmlRep = WebHTMLRepresentation::createInstance(static_cast<WebFrame*>(m_loader->frameLoader()->client()));
181        hr = htmlRep->QueryInterface(IID_IWebDocumentRepresentation, (void**) &m_representation);
182        htmlRep->Release();
183    }
184
185    return m_representation.copyRefTo(rep);
186}
187
188HRESULT STDMETHODCALLTYPE WebDataSource::webFrame(
189    /* [retval][out] */ IWebFrame** frame)
190{
191    *frame = static_cast<WebFrame*>(m_loader->frameLoader()->client());
192    (*frame)->AddRef();
193    return S_OK;
194}
195
196HRESULT STDMETHODCALLTYPE WebDataSource::initialRequest(
197    /* [retval][out] */ IWebURLRequest** request)
198{
199    *request = WebMutableURLRequest::createInstance(m_loader->originalRequest());
200    return S_OK;
201}
202
203HRESULT STDMETHODCALLTYPE WebDataSource::request(
204    /* [retval][out] */ IWebMutableURLRequest** request)
205{
206    *request = WebMutableURLRequest::createInstance(m_loader->request());
207    return S_OK;
208}
209
210HRESULT STDMETHODCALLTYPE WebDataSource::response(
211    /* [retval][out] */ IWebURLResponse** response)
212{
213    *response = WebURLResponse::createInstance(m_loader->response());
214    return S_OK;
215}
216
217HRESULT STDMETHODCALLTYPE WebDataSource::textEncodingName(
218    /* [retval][out] */ BSTR* name)
219{
220    String encoding = m_loader->overrideEncoding();
221    if (encoding.isNull())
222        encoding = m_loader->response().textEncodingName();
223
224    *name = BString(encoding).release();
225
226    return S_OK;
227}
228
229HRESULT STDMETHODCALLTYPE WebDataSource::isLoading(
230    /* [retval][out] */ BOOL* loading)
231{
232    *loading = m_loader->isLoadingInAPISense();
233    return S_OK;
234}
235
236HRESULT STDMETHODCALLTYPE WebDataSource::pageTitle(
237    /* [retval][out] */ BSTR* title)
238{
239    *title = BString(m_loader->title()).release();
240    return S_OK;
241}
242
243HRESULT STDMETHODCALLTYPE WebDataSource::unreachableURL(
244    /* [retval][out] */ BSTR* url)
245{
246    KURL unreachableURL = m_loader->unreachableURL();
247    BString urlString((LPOLESTR)unreachableURL.string().characters(), unreachableURL.string().length());
248
249    *url = urlString.release();
250    return S_OK;
251}
252
253HRESULT STDMETHODCALLTYPE WebDataSource::webArchive(
254    /* [retval][out] */ IWebArchive** /*archive*/)
255{
256    ASSERT_NOT_REACHED();
257    return E_NOTIMPL;
258}
259
260HRESULT STDMETHODCALLTYPE WebDataSource::mainResource(
261    /* [retval][out] */ IWebResource** /*resource*/)
262{
263    ASSERT_NOT_REACHED();
264    return E_NOTIMPL;
265}
266
267HRESULT STDMETHODCALLTYPE WebDataSource::subresources(
268    /* [retval][out] */ IEnumVARIANT** /*result*/)
269{
270    ASSERT_NOT_REACHED();
271    return E_NOTIMPL;
272}
273
274HRESULT STDMETHODCALLTYPE WebDataSource::subresourceForURL(
275    /* [in] */ BSTR url,
276    /* [retval][out] */ IWebResource** resource)
277{
278    if (!resource) {
279        ASSERT_NOT_REACHED();
280        return E_POINTER;
281    }
282
283    *resource = 0;
284
285    Document *doc = m_loader->frameLoader()->frame()->document();
286
287    if (!doc)
288        return E_FAIL;
289
290    CachedResource *cachedResource = doc->docLoader()->cachedResource(String(url));
291
292    if (!cachedResource)
293        return E_FAIL;
294
295    *resource = WebResource::createInstance(cachedResource->data(), cachedResource->response());
296    return S_OK;
297}
298
299HRESULT STDMETHODCALLTYPE WebDataSource::addSubresource(
300    /* [in] */ IWebResource* /*subresource*/)
301{
302    ASSERT_NOT_REACHED();
303    return E_NOTIMPL;
304}
305