2 * Copyright (C) 2012 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "NetworkResourceLoader.h"
29 #if ENABLE(NETWORK_PROCESS)
31 #include "BlockingResponseMap.h"
32 #include "DataReference.h"
34 #include "NetworkConnectionToWebProcess.h"
35 #include "NetworkProcess.h"
36 #include "NetworkProcessConnectionMessages.h"
37 #include "NetworkResourceLoadParameters.h"
38 #include "RemoteNetworkingContext.h"
39 #include "SharedMemory.h"
40 #include "WebCoreArgumentCoders.h"
41 #include <WebCore/NotImplemented.h>
42 #include <WebCore/ResourceBuffer.h>
43 #include <WebCore/ResourceHandle.h>
44 #include <wtf/MainThread.h>
46 using namespace WebCore;
50 NetworkResourceLoader::NetworkResourceLoader(const NetworkResourceLoadParameters& requestParameters, ResourceLoadIdentifier identifier, NetworkConnectionToWebProcess* connection)
51 : m_requestParameters(requestParameters)
52 , m_identifier(identifier)
53 , m_connection(connection)
55 ASSERT(isMainThread());
56 connection->registerObserver(this);
59 NetworkResourceLoader::~NetworkResourceLoader()
61 ASSERT(isMainThread());
64 m_connection->unregisterObserver(this);
67 ResourceLoadPriority NetworkResourceLoader::priority() const
69 return m_requestParameters.priority();
72 void NetworkResourceLoader::start()
74 ASSERT(isMainThread());
76 // Explicit ref() balanced by a deref() in NetworkResourceLoader::stop()
79 // FIXME (NetworkProcess): Create RemoteNetworkingContext with actual settings.
80 m_networkingContext = RemoteNetworkingContext::create(false, false);
82 // FIXME (NetworkProcess): Pass an actual value for defersLoading
83 m_handle = ResourceHandle::create(m_networkingContext.get(), m_requestParameters.request(), this, false /* defersLoading */, m_requestParameters.contentSniffingPolicy() == SniffContent);
86 static bool stopRequestsCalled = false;
88 static Mutex& requestsToStopMutex()
90 DEFINE_STATIC_LOCAL(Mutex, mutex, ());
94 static HashSet<NetworkResourceLoader*>& requestsToStop()
96 DEFINE_STATIC_LOCAL(HashSet<NetworkResourceLoader*>, requests, ());
100 void NetworkResourceLoader::scheduleStopOnMainThread()
102 MutexLocker locker(requestsToStopMutex());
104 requestsToStop().add(this);
105 if (!stopRequestsCalled) {
106 stopRequestsCalled = true;
107 callOnMainThread(NetworkResourceLoader::performStops, 0);
111 void NetworkResourceLoader::performStops(void*)
113 ASSERT(stopRequestsCalled);
115 Vector<NetworkResourceLoader*> requests;
117 MutexLocker locker(requestsToStopMutex());
118 copyToVector(requestsToStop(), requests);
119 requestsToStop().clear();
120 stopRequestsCalled = false;
123 for (size_t i = 0; i < requests.size(); ++i)
127 void NetworkResourceLoader::stop()
129 ASSERT(isMainThread());
131 // Remove this load identifier soon so we can start more network requests.
132 NetworkProcess::shared().networkResourceLoadScheduler().scheduleRemoveLoadIdentifier(m_identifier);
134 // Explicit deref() balanced by a ref() in NetworkResourceLoader::stop()
135 // This might cause the NetworkResourceLoader to be destroyed and therefore we do it last.
139 void NetworkResourceLoader::connectionToWebProcessDidClose(NetworkConnectionToWebProcess* connection)
141 ASSERT_ARG(connection, connection == m_connection.get());
142 m_connection->unregisterObserver(this);
146 void NetworkResourceLoader::didReceiveResponse(ResourceHandle*, const ResourceResponse& response)
148 // FIXME (NetworkProcess): Cache the response.
149 connectionToWebProcess()->connection()->send(Messages::NetworkProcessConnection::DidReceiveResponse(m_identifier, response), 0);
152 void NetworkResourceLoader::didReceiveData(ResourceHandle*, const char* data, int length, int encodedDataLength)
154 // FIXME (NetworkProcess): For the memory cache we'll also need to cache the response data here.
155 // Such buffering will need to be thread safe, as this callback is happening on a background thread.
157 CoreIPC::DataReference dataReference(reinterpret_cast<const uint8_t*>(data), length);
158 connectionToWebProcess()->connection()->send(Messages::NetworkProcessConnection::DidReceiveData(m_identifier, dataReference, encodedDataLength, false), 0);
161 void NetworkResourceLoader::didFinishLoading(ResourceHandle*, double finishTime)
163 // FIXME (NetworkProcess): For the memory cache we'll need to update the finished status of the cached resource here.
164 // Such bookkeeping will need to be thread safe, as this callback is happening on a background thread.
165 connectionToWebProcess()->connection()->send(Messages::NetworkProcessConnection::DidFinishResourceLoad(m_identifier, finishTime), 0);
166 scheduleStopOnMainThread();
169 void NetworkResourceLoader::didFail(ResourceHandle*, const ResourceError& error)
171 // FIXME (NetworkProcess): For the memory cache we'll need to update the finished status of the cached resource here.
172 // Such bookkeeping will need to be thread safe, as this callback is happening on a background thread.
173 connectionToWebProcess()->connection()->send(Messages::NetworkProcessConnection::DidFailResourceLoad(m_identifier, error), 0);
174 scheduleStopOnMainThread();
177 static BlockingResponseMap<ResourceRequest*>& responseMap()
179 AtomicallyInitializedStatic(BlockingResponseMap<ResourceRequest*>&, responseMap = *new BlockingResponseMap<ResourceRequest*>);
183 static uint64_t generateWillSendRequestID()
185 static int64_t uniqueWillSendRequestID;
186 return OSAtomicIncrement64Barrier(&uniqueWillSendRequestID);
189 void didReceiveWillSendRequestHandled(uint64_t requestID, const ResourceRequest& request)
191 responseMap().didReceiveResponse(requestID, adoptPtr(new ResourceRequest(request)));
194 void NetworkResourceLoader::willSendRequest(ResourceHandle*, ResourceRequest& request, const ResourceResponse& redirectResponse)
196 // We only expect to get the willSendRequest callback from ResourceHandle as the result of a redirect
197 ASSERT(!redirectResponse.isNull());
199 uint64_t requestID = generateWillSendRequestID();
201 if (!connectionToWebProcess()->connection()->send(Messages::NetworkProcessConnection::WillSendRequest(requestID, m_identifier, request, redirectResponse), 0)) {
202 // FIXME (NetworkProcess): What should we do if we can't send the message?
206 OwnPtr<ResourceRequest> newRequest = responseMap().waitForResponse(requestID);
207 request = *newRequest;
209 RunLoop::main()->dispatch(WTF::bind(&NetworkResourceLoadScheduler::receivedRedirect, &NetworkProcess::shared().networkResourceLoadScheduler(), m_identifier, request.url()));
212 // FIXME (NetworkProcess): Many of the following ResourceHandleClient methods definitely need implementations. A few will not.
213 // Once we know what they are they can be removed.
215 void NetworkResourceLoader::didSendData(WebCore::ResourceHandle*, unsigned long long /*bytesSent*/, unsigned long long /*totalBytesToBeSent*/)
220 void NetworkResourceLoader::didReceiveCachedMetadata(WebCore::ResourceHandle*, const char*, int)
225 void NetworkResourceLoader::wasBlocked(WebCore::ResourceHandle*)
230 void NetworkResourceLoader::cannotShowURL(WebCore::ResourceHandle*)
235 void NetworkResourceLoader::willCacheResponse(WebCore::ResourceHandle*, WebCore::CacheStoragePolicy&)
240 bool NetworkResourceLoader::shouldUseCredentialStorage(WebCore::ResourceHandle*)
246 void NetworkResourceLoader::didReceiveAuthenticationChallenge(WebCore::ResourceHandle*, const WebCore::AuthenticationChallenge&)
251 void NetworkResourceLoader::didCancelAuthenticationChallenge(WebCore::ResourceHandle*, const WebCore::AuthenticationChallenge&)
256 void NetworkResourceLoader::receivedCancellation(WebCore::ResourceHandle*, const WebCore::AuthenticationChallenge&)
261 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
262 bool NetworkResourceLoader::canAuthenticateAgainstProtectionSpace(WebCore::ResourceHandle*, const WebCore::ProtectionSpace&)
269 #if HAVE(NETWORK_CFDATA_ARRAY_CALLBACK)
270 bool NetworkResourceLoader::supportsDataArray()
276 void NetworkResourceLoader::didReceiveDataArray(WebCore::ResourceHandle*, CFArrayRef)
284 CFCachedURLResponseRef NetworkResourceLoader::willCacheResponse(WebCore::ResourceHandle*, CFCachedURLResponseRef response)
290 NSCachedURLResponse* NetworkResourceLoader::willCacheResponse(WebCore::ResourceHandle*, NSCachedURLResponse* response)
297 void NetworkResourceLoader::willStopBufferingData(WebCore::ResourceHandle*, const char*, int)
301 #endif // PLATFORM(MAC)
304 WebCore::AsyncFileStream* NetworkResourceLoader::createAsyncFileStream(WebCore::FileStreamClient*)
311 } // namespace WebKit
313 #endif // ENABLE(NETWORK_PROCESS)