262ceb7f67028dc6697d8cb2ea19b74a5b664ab3
[WebKit-https.git] / Source / WebCore / platform / network / qt / ResourceHandleQt.cpp
1 /*
2  * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
3  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
4  * Copyright (C) 2008 Holger Hans Peter Freyther
5  *
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
21  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
25  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "config.h"
31 #include "ResourceHandle.h"
32
33 #include "CachedResourceLoader.h"
34 #include "Frame.h"
35 #include "FrameNetworkingContext.h"
36 #include "NotImplemented.h"
37 #include "Page.h"
38 #include "QNetworkReplyHandler.h"
39 #include "ResourceHandleClient.h"
40 #include "ResourceHandleInternal.h"
41 #include "SharedBuffer.h"
42
43 #include <QAbstractNetworkCache>
44 #include <QCoreApplication>
45 #include <QUrl>
46 #include <QNetworkAccessManager>
47 #include <QNetworkRequest>
48 #include <QNetworkReply>
49
50 namespace WebCore {
51
52 class WebCoreSynchronousLoader : public ResourceHandleClient {
53 public:
54     WebCoreSynchronousLoader(ResourceError& error, ResourceResponse& response, Vector<char>& data)
55         : m_error(error)
56         , m_response(response)
57         , m_data(data)
58     {}
59
60     virtual void willSendRequest(ResourceHandle*, ResourceRequest&, const ResourceResponse&);
61     virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse& response) { m_response = response; }
62     virtual void didReceiveData(ResourceHandle*, const char* data, int length, int) { m_data.append(data, length); }
63     virtual void didFinishLoading(ResourceHandle*, double /*finishTime*/) {}
64     virtual void didFail(ResourceHandle*, const ResourceError& error) { m_error = error; }
65 private:
66     ResourceError& m_error;
67     ResourceResponse& m_response;
68     Vector<char>& m_data;
69 };
70
71 void WebCoreSynchronousLoader::willSendRequest(ResourceHandle* handle, ResourceRequest& request, const ResourceResponse& /*redirectResponse*/)
72 {
73     // FIXME: This needs to be fixed to follow the redirect correctly even for cross-domain requests.
74     if (!protocolHostAndPortAreEqual(handle->firstRequest().url(), request.url())) {
75         ASSERT(m_error.isNull());
76         m_error.setIsCancellation(true);
77         request = ResourceRequest();
78         return;
79     }
80 }
81
82 ResourceHandleInternal::~ResourceHandleInternal()
83 {
84 }
85
86 ResourceHandle::~ResourceHandle()
87 {
88     if (d->m_job)
89         cancel();
90 }
91
92 bool ResourceHandle::start(NetworkingContext* context)
93 {
94     // If NetworkingContext is invalid then we are no longer attached to a Page,
95     // this must be an attempted load from an unload event handler, so let's just block it.
96     if (context && !context->isValid())
97         return false;
98
99     if (!d->m_user.isEmpty() || !d->m_pass.isEmpty()) {
100         // If credentials were specified for this request, add them to the url,
101         // so that they will be passed to QNetworkRequest.
102         KURL urlWithCredentials(firstRequest().url());
103         urlWithCredentials.setUser(d->m_user);
104         urlWithCredentials.setPass(d->m_pass);
105         d->m_firstRequest.setURL(urlWithCredentials);
106     }
107
108     getInternal()->m_context = context;
109     ResourceHandleInternal *d = getInternal();
110     d->m_job = new QNetworkReplyHandler(this, QNetworkReplyHandler::AsynchronousLoad, d->m_defersLoading);
111     return true;
112 }
113
114 void ResourceHandle::cancel()
115 {
116     if (d->m_job) {
117         d->m_job->abort();
118         d->m_job = 0;
119     }
120 }
121
122 bool ResourceHandle::loadsBlocked()
123 {
124     return false;
125 }
126
127 bool ResourceHandle::willLoadFromCache(ResourceRequest& request, Frame* frame)
128 {
129     if (!frame)
130         return false;
131
132     QNetworkAccessManager* manager = 0;
133     QAbstractNetworkCache* cache = 0;
134     if (frame->loader()->networkingContext()) {
135         manager = frame->loader()->networkingContext()->networkAccessManager();
136         cache = manager->cache();
137     }
138
139     if (!cache)
140         return false;
141
142     QNetworkCacheMetaData data = cache->metaData(request.url());
143     if (data.isValid()) {
144         request.setCachePolicy(ReturnCacheDataDontLoad);
145         return true;
146     }
147
148     return false;
149 }
150
151 void ResourceHandle::loadResourceSynchronously(NetworkingContext* context, const ResourceRequest& request, StoredCredentials /*storedCredentials*/, ResourceError& error, ResourceResponse& response, Vector<char>& data)
152 {
153     WebCoreSynchronousLoader syncLoader(error, response, data);
154     RefPtr<ResourceHandle> handle = adoptRef(new ResourceHandle(request, &syncLoader, true, false));
155
156     ResourceHandleInternal* d = handle->getInternal();
157     if (!d->m_user.isEmpty() || !d->m_pass.isEmpty()) {
158         // If credentials were specified for this request, add them to the url,
159         // so that they will be passed to QNetworkRequest.
160         KURL urlWithCredentials(d->m_firstRequest.url());
161         urlWithCredentials.setUser(d->m_user);
162         urlWithCredentials.setPass(d->m_pass);
163         d->m_firstRequest.setURL(urlWithCredentials);
164     }
165     d->m_context = context;
166
167     // starting in deferred mode gives d->m_job the chance of being set before sending the request.
168     d->m_job = new QNetworkReplyHandler(handle.get(), QNetworkReplyHandler::SynchronousLoad, true);
169     d->m_job->setLoadingDeferred(false);
170 }
171
172 void ResourceHandle::platformSetDefersLoading(bool defers)
173 {
174     if (!d->m_job)
175         return;
176     d->m_job->setLoadingDeferred(defers);
177 }
178
179 } // namespace WebCore