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 "NetworkingContext.h"
33#include "NotImplemented.h"
34#include "ResourceHandleInternal.h"
35#include "ResourceHandleManager.h"
36#include "SharedBuffer.h"
37
38#if PLATFORM(WIN) && USE(CF)
39#include <wtf/PassRefPtr.h>
40#include <wtf/RetainPtr.h>
41#endif
42
43namespace WebCore {
44
45class WebCoreSynchronousLoader : public ResourceHandleClient {
46public:
47    WebCoreSynchronousLoader();
48
49    virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&);
50    virtual void didReceiveData(ResourceHandle*, const char*, int, int encodedDataLength);
51    virtual void didFinishLoading(ResourceHandle*, double /*finishTime*/);
52    virtual void didFail(ResourceHandle*, const ResourceError&);
53
54    ResourceResponse resourceResponse() const { return m_response; }
55    ResourceError resourceError() const { return m_error; }
56    Vector<char> data() const { return m_data; }
57
58private:
59    ResourceResponse m_response;
60    ResourceError m_error;
61    Vector<char> m_data;
62};
63
64WebCoreSynchronousLoader::WebCoreSynchronousLoader()
65{
66}
67
68void WebCoreSynchronousLoader::didReceiveResponse(ResourceHandle*, const ResourceResponse& response)
69{
70    m_response = response;
71}
72
73void WebCoreSynchronousLoader::didReceiveData(ResourceHandle*, const char* data, int length, int)
74{
75    m_data.append(data, length);
76}
77
78void WebCoreSynchronousLoader::didFinishLoading(ResourceHandle*, double)
79{
80}
81
82void WebCoreSynchronousLoader::didFail(ResourceHandle*, const ResourceError& error)
83{
84    m_error = error;
85}
86
87ResourceHandleInternal::~ResourceHandleInternal()
88{
89    fastFree(m_url);
90    if (m_customHeaders)
91        curl_slist_free_all(m_customHeaders);
92}
93
94ResourceHandle::~ResourceHandle()
95{
96    cancel();
97}
98
99bool ResourceHandle::start()
100{
101    // The frame could be null if the ResourceHandle is not associated to any
102    // Frame, e.g. if we are downloading a file.
103    // If the frame is not null but the page is null this must be an attempted
104    // load from an unload handler, so let's just block it.
105    // If both the frame and the page are not null the context is valid.
106    if (d->m_context && !d->m_context->isValid())
107        return false;
108
109    ResourceHandleManager::sharedInstance()->add(this);
110    return true;
111}
112
113void ResourceHandle::cancel()
114{
115    ResourceHandleManager::sharedInstance()->cancel(this);
116}
117
118#if PLATFORM(WIN) && USE(CF)
119static HashSet<String>& allowsAnyHTTPSCertificateHosts()
120{
121    static HashSet<String> hosts;
122
123    return hosts;
124}
125
126void ResourceHandle::setHostAllowsAnyHTTPSCertificate(const String& host)
127{
128    allowsAnyHTTPSCertificateHosts().add(host.lower());
129}
130#endif
131
132#if PLATFORM(WIN) && USE(CF)
133// FIXME:  The CFDataRef will need to be something else when
134// building without
135static HashMap<String, RetainPtr<CFDataRef> >& clientCerts()
136{
137    static HashMap<String, RetainPtr<CFDataRef> > certs;
138    return certs;
139}
140
141void ResourceHandle::setClientCertificate(const String& host, CFDataRef cert)
142{
143    clientCerts().set(host.lower(), cert);
144}
145#endif
146
147void ResourceHandle::platformSetDefersLoading(bool defers)
148{
149    if (!d->m_handle)
150        return;
151
152    if (defers) {
153        CURLcode error = curl_easy_pause(d->m_handle, CURLPAUSE_ALL);
154        // If we could not defer the handle, so don't do it.
155        if (error != CURLE_OK)
156            return;
157    } else {
158        CURLcode error = curl_easy_pause(d->m_handle, CURLPAUSE_CONT);
159        if (error != CURLE_OK)
160            // Restarting the handle has failed so just cancel it.
161            cancel();
162    }
163}
164
165bool ResourceHandle::loadsBlocked()
166{
167    notImplemented();
168    return false;
169}
170
171void ResourceHandle::platformLoadResourceSynchronously(NetworkingContext* context, const ResourceRequest& request, StoredCredentials storedCredentials, ResourceError& error, ResourceResponse& response, Vector<char>& data)
172{
173    WebCoreSynchronousLoader syncLoader;
174    RefPtr<ResourceHandle> handle = adoptRef(new ResourceHandle(context, request, &syncLoader, true, false));
175
176    ResourceHandleManager* manager = ResourceHandleManager::sharedInstance();
177
178    manager->dispatchSynchronousJob(handle.get());
179
180    error = syncLoader.resourceError();
181    data = syncLoader.data();
182    response = syncLoader.resourceResponse();
183}
184
185//stubs needed for windows version
186void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChallenge&)
187{
188    notImplemented();
189}
190
191void ResourceHandle::receivedCredential(const AuthenticationChallenge&, const Credential&)
192{
193    notImplemented();
194}
195
196void ResourceHandle::receivedRequestToContinueWithoutCredential(const AuthenticationChallenge&)
197{
198    notImplemented();
199}
200
201void ResourceHandle::receivedCancellation(const AuthenticationChallenge&)
202{
203    notImplemented();
204}
205
206} // namespace WebCore
207