[iOS] Subresources referenced in converted QuickLook documents sometimes fail to...
[WebKit-https.git] / Source / WebKit2 / WebProcess / Network / WebResourceLoader.cpp
1 /*
2  * Copyright (C) 2012, 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "WebResourceLoader.h"
28
29 #if ENABLE(NETWORK_PROCESS)
30
31 #include "DataReference.h"
32 #include "Logging.h"
33 #include "NetworkProcessConnection.h"
34 #include "NetworkResourceLoaderMessages.h"
35 #include "WebCoreArgumentCoders.h"
36 #include "WebErrors.h"
37 #include "WebProcess.h"
38 #include <WebCore/ApplicationCacheHost.h>
39 #include <WebCore/CertificateInfo.h>
40 #include <WebCore/DocumentLoader.h>
41 #include <WebCore/ResourceBuffer.h>
42 #include <WebCore/ResourceError.h>
43 #include <WebCore/ResourceLoader.h>
44
45 using namespace WebCore;
46
47 namespace WebKit {
48
49 PassRefPtr<WebResourceLoader> WebResourceLoader::create(PassRefPtr<ResourceLoader> coreLoader)
50 {
51     return adoptRef(new WebResourceLoader(coreLoader));
52 }
53
54 WebResourceLoader::WebResourceLoader(PassRefPtr<WebCore::ResourceLoader> coreLoader)
55     : m_coreLoader(coreLoader)
56 {
57 }
58
59 WebResourceLoader::~WebResourceLoader()
60 {
61 }
62
63 IPC::Connection* WebResourceLoader::messageSenderConnection()
64 {
65     return WebProcess::shared().networkConnection()->connection();
66 }
67
68 uint64_t WebResourceLoader::messageSenderDestinationID()
69 {
70     return m_coreLoader->identifier();
71 }
72
73 void WebResourceLoader::cancelResourceLoader()
74 {
75     m_coreLoader->cancel();
76 }
77
78 void WebResourceLoader::detachFromCoreLoader()
79 {
80     m_coreLoader = 0;
81 }
82
83 void WebResourceLoader::willSendRequest(const ResourceRequest& proposedRequest, const ResourceResponse& redirectResponse)
84 {
85     LOG(Network, "(WebProcess) WebResourceLoader::willSendRequest to '%s'", proposedRequest.url().string().utf8().data());
86
87     Ref<WebResourceLoader> protect(*this);
88
89     ResourceRequest newRequest = proposedRequest;
90     if (m_coreLoader->documentLoader()->applicationCacheHost()->maybeLoadFallbackForRedirect(m_coreLoader.get(), newRequest, redirectResponse))
91         return;
92     m_coreLoader->willSendRequest(newRequest, redirectResponse);
93     
94     if (!m_coreLoader)
95         return;
96     
97     send(Messages::NetworkResourceLoader::ContinueWillSendRequest(newRequest));
98 }
99
100 void WebResourceLoader::didSendData(uint64_t bytesSent, uint64_t totalBytesToBeSent)
101 {
102     m_coreLoader->didSendData(bytesSent, totalBytesToBeSent);
103 }
104
105 void WebResourceLoader::didReceiveResponseWithCertificateInfo(const ResourceResponse& response, const CertificateInfo& certificateInfo, bool needsContinueDidReceiveResponseMessage)
106 {
107     LOG(Network, "(WebProcess) WebResourceLoader::didReceiveResponseWithCertificateInfo for '%s'. Status %d.", m_coreLoader->url().string().utf8().data(), response.httpStatusCode());
108
109     Ref<WebResourceLoader> protect(*this);
110
111     ResourceResponse responseCopy(response);
112
113     // FIXME: This should use CertificateInfo to avoid the platform ifdefs. See https://bugs.webkit.org/show_bug.cgi?id=124724.
114 #if PLATFORM(COCOA)
115     responseCopy.setCertificateChain(certificateInfo.certificateChain());
116 #elif USE(SOUP)
117     responseCopy.setSoupMessageCertificate(certificateInfo.certificate());
118     responseCopy.setSoupMessageTLSErrors(certificateInfo.tlsErrors());
119 #endif
120
121     if (m_coreLoader->documentLoader()->applicationCacheHost()->maybeLoadFallbackForResponse(m_coreLoader.get(), responseCopy))
122         return;
123
124 #if USE(QUICK_LOOK)
125     // Refrain from calling didReceiveResponse if QuickLook will convert this response, since the MIME type of the
126     // converted resource isn't yet known. WebResourceLoaderQuickLookDelegate will later call didReceiveResponse upon
127     // receiving the converted data.
128     m_coreLoader->documentLoader()->setQuickLookHandle(QuickLookHandle::create(resourceLoader(), responseCopy.nsURLResponse()));
129     if (!m_coreLoader->documentLoader()->quickLookHandle())
130 #endif
131         m_coreLoader->didReceiveResponse(responseCopy);
132
133     // If m_coreLoader becomes null as a result of the didReceiveResponse callback, we can't use the send function(). 
134     if (!m_coreLoader)
135         return;
136
137     if (needsContinueDidReceiveResponseMessage)
138         send(Messages::NetworkResourceLoader::ContinueDidReceiveResponse());
139 }
140
141 void WebResourceLoader::didReceiveData(const IPC::DataReference& data, int64_t encodedDataLength)
142 {
143     LOG(Network, "(WebProcess) WebResourceLoader::didReceiveData of size %i for '%s'", (int)data.size(), m_coreLoader->url().string().utf8().data());
144
145 #if USE(QUICK_LOOK)
146     if (QuickLookHandle* quickLookHandle = m_coreLoader->documentLoader()->quickLookHandle()) {
147         if (quickLookHandle->didReceiveData(adoptCF(CFDataCreate(kCFAllocatorDefault, data.data(), data.size())).get()))
148             return;
149     }
150 #endif
151     m_coreLoader->didReceiveData(reinterpret_cast<const char*>(data.data()), data.size(), encodedDataLength, DataPayloadBytes);
152 }
153
154 void WebResourceLoader::didFinishResourceLoad(double finishTime)
155 {
156     LOG(Network, "(WebProcess) WebResourceLoader::didFinishResourceLoad for '%s'", m_coreLoader->url().string().utf8().data());
157
158 #if USE(QUICK_LOOK)
159     if (QuickLookHandle* quickLookHandle = m_coreLoader->documentLoader()->quickLookHandle()) {
160         if (quickLookHandle->didFinishLoading())
161             return;
162     }
163 #endif
164     m_coreLoader->didFinishLoading(finishTime);
165 }
166
167 void WebResourceLoader::didFailResourceLoad(const ResourceError& error)
168 {
169     LOG(Network, "(WebProcess) WebResourceLoader::didFailResourceLoad for '%s'", m_coreLoader->url().string().utf8().data());
170     
171 #if USE(QUICK_LOOK)
172     if (QuickLookHandle* quickLookHandle = m_coreLoader->documentLoader()->quickLookHandle())
173         quickLookHandle->didFail();
174 #endif
175     if (m_coreLoader->documentLoader()->applicationCacheHost()->maybeLoadFallbackForError(m_coreLoader.get(), error))
176         return;
177     m_coreLoader->didFail(error);
178 }
179
180 #if ENABLE(SHAREABLE_RESOURCE)
181 void WebResourceLoader::didReceiveResource(const ShareableResource::Handle& handle, double finishTime)
182 {
183     LOG(Network, "(WebProcess) WebResourceLoader::didReceiveResource for '%s'", m_coreLoader->url().string().utf8().data());
184
185 #if USE(QUICK_LOOK)
186     if (QuickLookHandle* quickLookHandle = m_coreLoader->documentLoader()->quickLookHandle()) {
187         RetainPtr<CFDataRef> cfBuffer = handle.tryWrapInCFData();
188         if (cfBuffer) {
189             if (quickLookHandle->didReceiveData(cfBuffer.get())) {
190                 quickLookHandle->didFinishLoading();
191                 return;
192             }
193         } else
194             quickLookHandle->didFail();
195     }
196 #endif
197
198     RefPtr<SharedBuffer> buffer = handle.tryWrapInSharedBuffer();
199     if (!buffer) {
200         LOG_ERROR("Unable to create buffer from ShareableResource sent from the network process.");
201         m_coreLoader->didFail(internalError(m_coreLoader->request().url()));
202         return;
203     }
204
205     Ref<WebResourceLoader> protect(*this);
206
207     // Only send data to the didReceiveData callback if it exists.
208     if (buffer->size())
209         m_coreLoader->didReceiveBuffer(buffer.get(), buffer->size(), DataPayloadWholeResource);
210
211     if (!m_coreLoader)
212         return;
213
214     m_coreLoader->didFinishLoading(finishTime);
215 }
216 #endif
217
218 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
219 void WebResourceLoader::canAuthenticateAgainstProtectionSpace(const ProtectionSpace& protectionSpace)
220 {
221     Ref<WebResourceLoader> protect(*this);
222
223     bool result = m_coreLoader->canAuthenticateAgainstProtectionSpace(protectionSpace);
224
225     if (!m_coreLoader)
226         return;
227
228     send(Messages::NetworkResourceLoader::ContinueCanAuthenticateAgainstProtectionSpace(result));
229 }
230 #endif
231
232 } // namespace WebKit
233
234 #endif // ENABLE(NETWORK_PROCESS)