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