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/CachedResourceLoader.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
122HRESULT STDMETHODCALLTYPE WebDataSource::setDeferMainResourceDataLoad(
123    /* [in] */ BOOL flag)
124{
125    if (!m_loader)
126        return E_FAIL;
127
128    m_loader->setDeferMainResourceDataLoad(flag);
129    return S_OK;
130}
131
132// IUnknown -------------------------------------------------------------------
133
134HRESULT STDMETHODCALLTYPE WebDataSource::QueryInterface(REFIID riid, void** ppvObject)
135{
136    *ppvObject = 0;
137    if (IsEqualGUID(riid, IID_WebDataSource))
138        *ppvObject = this;
139    else if (IsEqualGUID(riid, IID_IUnknown))
140        *ppvObject = static_cast<IWebDataSource*>(this);
141    else if (IsEqualGUID(riid, IID_IWebDataSource))
142        *ppvObject = static_cast<IWebDataSource*>(this);
143    else if (IsEqualGUID(riid, IID_IWebDataSourcePrivate))
144        *ppvObject = static_cast<IWebDataSourcePrivate*>(this);
145    else
146        return E_NOINTERFACE;
147
148    AddRef();
149    return S_OK;
150}
151
152ULONG STDMETHODCALLTYPE WebDataSource::AddRef(void)
153{
154    return ++m_refCount;
155}
156
157ULONG STDMETHODCALLTYPE WebDataSource::Release(void)
158{
159    ULONG newRef = --m_refCount;
160    if (!newRef)
161        delete(this);
162
163    return newRef;
164}
165
166// IWebDataSource --------------------------------------------------------------
167
168HRESULT STDMETHODCALLTYPE WebDataSource::initWithRequest(
169    /* [in] */ IWebURLRequest* /*request*/)
170{
171    ASSERT_NOT_REACHED();
172    return E_NOTIMPL;
173}
174
175HRESULT STDMETHODCALLTYPE WebDataSource::data(
176    /* [retval][out] */ IStream** stream)
177{
178    *stream = 0;
179    if (!m_loader)
180        return E_FAIL;
181
182    return MemoryStream::createInstance(m_loader->mainResourceData()).copyRefTo(stream);
183}
184
185HRESULT STDMETHODCALLTYPE WebDataSource::representation(
186    /* [retval][out] */ IWebDocumentRepresentation** rep)
187{
188    HRESULT hr = S_OK;
189    if (!m_representation) {
190        WebHTMLRepresentation* htmlRep = WebHTMLRepresentation::createInstance(static_cast<WebFrame*>(m_loader->frameLoader()->client()));
191        hr = htmlRep->QueryInterface(IID_IWebDocumentRepresentation, (void**) &m_representation);
192        htmlRep->Release();
193    }
194
195    return m_representation.copyRefTo(rep);
196}
197
198HRESULT STDMETHODCALLTYPE WebDataSource::webFrame(
199    /* [retval][out] */ IWebFrame** frame)
200{
201    *frame = static_cast<WebFrame*>(m_loader->frameLoader()->client());
202    (*frame)->AddRef();
203    return S_OK;
204}
205
206HRESULT STDMETHODCALLTYPE WebDataSource::initialRequest(
207    /* [retval][out] */ IWebURLRequest** request)
208{
209    *request = WebMutableURLRequest::createInstance(m_loader->originalRequest());
210    return S_OK;
211}
212
213HRESULT STDMETHODCALLTYPE WebDataSource::request(
214    /* [retval][out] */ IWebMutableURLRequest** request)
215{
216    *request = WebMutableURLRequest::createInstance(m_loader->request());
217    return S_OK;
218}
219
220HRESULT STDMETHODCALLTYPE WebDataSource::response(
221    /* [retval][out] */ IWebURLResponse** response)
222{
223    *response = WebURLResponse::createInstance(m_loader->response());
224    return S_OK;
225}
226
227HRESULT STDMETHODCALLTYPE WebDataSource::textEncodingName(
228    /* [retval][out] */ BSTR* name)
229{
230    String encoding = m_loader->overrideEncoding();
231    if (encoding.isNull())
232        encoding = m_loader->response().textEncodingName();
233
234    *name = BString(encoding).release();
235
236    return S_OK;
237}
238
239HRESULT STDMETHODCALLTYPE WebDataSource::isLoading(
240    /* [retval][out] */ BOOL* loading)
241{
242    *loading = m_loader->isLoadingInAPISense();
243    return S_OK;
244}
245
246HRESULT STDMETHODCALLTYPE WebDataSource::pageTitle(
247    /* [retval][out] */ BSTR* title)
248{
249    *title = BString(m_loader->title().string()).release();
250    return S_OK;
251}
252
253HRESULT STDMETHODCALLTYPE WebDataSource::unreachableURL(
254    /* [retval][out] */ BSTR* url)
255{
256    KURL unreachableURL = m_loader->unreachableURL();
257    BString urlString((LPOLESTR)unreachableURL.string().characters(), unreachableURL.string().length());
258
259    *url = urlString.release();
260    return S_OK;
261}
262
263HRESULT STDMETHODCALLTYPE WebDataSource::webArchive(
264    /* [retval][out] */ IWebArchive** /*archive*/)
265{
266    ASSERT_NOT_REACHED();
267    return E_NOTIMPL;
268}
269
270HRESULT STDMETHODCALLTYPE WebDataSource::mainResource(
271    /* [retval][out] */ IWebResource** /*resource*/)
272{
273    ASSERT_NOT_REACHED();
274    return E_NOTIMPL;
275}
276
277HRESULT STDMETHODCALLTYPE WebDataSource::subresources(
278    /* [retval][out] */ IEnumVARIANT** /*result*/)
279{
280    ASSERT_NOT_REACHED();
281    return E_NOTIMPL;
282}
283
284HRESULT STDMETHODCALLTYPE WebDataSource::subresourceForURL(
285    /* [in] */ BSTR url,
286    /* [retval][out] */ IWebResource** resource)
287{
288    if (!resource) {
289        ASSERT_NOT_REACHED();
290        return E_POINTER;
291    }
292
293    *resource = 0;
294
295    Document *doc = m_loader->frameLoader()->frame()->document();
296
297    if (!doc)
298        return E_FAIL;
299
300    CachedResource *cachedResource = doc->cachedResourceLoader()->cachedResource(String(url));
301
302    if (!cachedResource)
303        return E_FAIL;
304
305    *resource = WebResource::createInstance(cachedResource->data(), cachedResource->response());
306    return S_OK;
307}
308
309HRESULT STDMETHODCALLTYPE WebDataSource::addSubresource(
310    /* [in] */ IWebResource* /*subresource*/)
311{
312    ASSERT_NOT_REACHED();
313    return E_NOTIMPL;
314}
315