1/*
2 * Copyright (C) 2004, 2006 Apple Computer, Inc.  All rights reserved.
3 * Copyright (C) 2005, 2006 Michael Emmel mike.emmel@gmail.com
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "config.h"
29#include "ResourceHandle.h"
30
31#include "CachedResourceLoader.h"
32#include "NotImplemented.h"
33#include "ResourceHandleInternal.h"
34#include "ResourceHandleManager.h"
35#include "SharedBuffer.h"
36
37#if PLATFORM(WIN) && USE(CF)
38#include <wtf/PassRefPtr.h>
39#include <wtf/RetainPtr.h>
40#endif
41
42namespace WebCore {
43
44class WebCoreSynchronousLoader : public ResourceHandleClient {
45public:
46    WebCoreSynchronousLoader();
47
48    virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&);
49    virtual void didReceiveData(ResourceHandle*, const char*, int, int encodedDataLength);
50    virtual void didFinishLoading(ResourceHandle*, double /*finishTime*/);
51    virtual void didFail(ResourceHandle*, const ResourceError&);
52
53    ResourceResponse resourceResponse() const { return m_response; }
54    ResourceError resourceError() const { return m_error; }
55    Vector<char> data() const { return m_data; }
56
57private:
58    ResourceResponse m_response;
59    ResourceError m_error;
60    Vector<char> m_data;
61};
62
63WebCoreSynchronousLoader::WebCoreSynchronousLoader()
64{
65}
66
67void WebCoreSynchronousLoader::didReceiveResponse(ResourceHandle*, const ResourceResponse& response)
68{
69    m_response = response;
70}
71
72void WebCoreSynchronousLoader::didReceiveData(ResourceHandle*, const char* data, int length, int)
73{
74    m_data.append(data, length);
75}
76
77void WebCoreSynchronousLoader::didFinishLoading(ResourceHandle*, double)
78{
79}
80
81void WebCoreSynchronousLoader::didFail(ResourceHandle*, const ResourceError& error)
82{
83    m_error = error;
84}
85
86ResourceHandleInternal::~ResourceHandleInternal()
87{
88    fastFree(m_url);
89    if (m_customHeaders)
90        curl_slist_free_all(m_customHeaders);
91}
92
93ResourceHandle::~ResourceHandle()
94{
95    cancel();
96}
97
98bool ResourceHandle::start(NetworkingContext* context)
99{
100    // The frame could be null if the ResourceHandle is not associated to any
101    // Frame, e.g. if we are downloading a file.
102    // If the frame is not null but the page is null this must be an attempted
103    // load from an unload handler, so let's just block it.
104    // If both the frame and the page are not null the context is valid.
105    if (context && !context->isValid())
106        return false;
107
108    ResourceHandleManager::sharedInstance()->add(this);
109    return true;
110}
111
112void ResourceHandle::cancel()
113{
114    ResourceHandleManager::sharedInstance()->cancel(this);
115}
116
117PassRefPtr<SharedBuffer> ResourceHandle::bufferedData()
118{
119    return 0;
120}
121
122bool ResourceHandle::supportsBufferedData()
123{
124    return false;
125}
126
127#if PLATFORM(WIN) && USE(CF)
128static HashSet<String>& allowsAnyHTTPSCertificateHosts()
129{
130    static HashSet<String> hosts;
131
132    return hosts;
133}
134
135void ResourceHandle::setHostAllowsAnyHTTPSCertificate(const String& host)
136{
137    allowsAnyHTTPSCertificateHosts().add(host.lower());
138}
139#endif
140
141#if PLATFORM(WIN) && USE(CF)
142// FIXME:  The CFDataRef will need to be something else when
143// building without
144static HashMap<String, RetainPtr<CFDataRef> >& clientCerts()
145{
146    static HashMap<String, RetainPtr<CFDataRef> > certs;
147    return certs;
148}
149
150void ResourceHandle::setClientCertificate(const String& host, CFDataRef cert)
151{
152    clientCerts().set(host.lower(), cert);
153}
154#endif
155
156void ResourceHandle::platformSetDefersLoading(bool defers)
157{
158#if LIBCURL_VERSION_NUM > 0x071200
159    if (!d->m_handle)
160        return;
161
162    if (defers) {
163        CURLcode error = curl_easy_pause(d->m_handle, CURLPAUSE_ALL);
164        // If we could not defer the handle, so don't do it.
165        if (error != CURLE_OK)
166            return;
167    } else {
168        CURLcode error = curl_easy_pause(d->m_handle, CURLPAUSE_CONT);
169        if (error != CURLE_OK)
170            // Restarting the handle has failed so just cancel it.
171            cancel();
172    }
173#else
174    LOG_ERROR("Deferred loading is implemented if libcURL version is above 7.18.0");
175#endif
176}
177
178bool ResourceHandle::willLoadFromCache(ResourceRequest&, Frame*)
179{
180    notImplemented();
181    return false;
182}
183
184bool ResourceHandle::loadsBlocked()
185{
186    notImplemented();
187    return false;
188}
189
190void ResourceHandle::loadResourceSynchronously(NetworkingContext*, const ResourceRequest& request, StoredCredentials storedCredentials, ResourceError& error, ResourceResponse& response, Vector<char>& data)
191{
192    WebCoreSynchronousLoader syncLoader;
193    RefPtr<ResourceHandle> handle = adoptRef(new ResourceHandle(request, &syncLoader, true, false));
194
195    ResourceHandleManager* manager = ResourceHandleManager::sharedInstance();
196
197    manager->dispatchSynchronousJob(handle.get());
198
199    error = syncLoader.resourceError();
200    data = syncLoader.data();
201    response = syncLoader.resourceResponse();
202}
203
204//stubs needed for windows version
205void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChallenge&)
206{
207    notImplemented();
208}
209
210void ResourceHandle::receivedCredential(const AuthenticationChallenge&, const Credential&)
211{
212    notImplemented();
213}
214
215void ResourceHandle::receivedRequestToContinueWithoutCredential(const AuthenticationChallenge&)
216{
217    notImplemented();
218}
219
220void ResourceHandle::receivedCancellation(const AuthenticationChallenge&)
221{
222    notImplemented();
223}
224
225} // namespace WebCore
226