NetworkResourceLoader.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. /*
  2. * Copyright (C) 2012 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. #include "config.h"
  26. #include "NetworkResourceLoader.h"
  27. #if ENABLE(NETWORK_PROCESS)
  28. #include "AsynchronousNetworkLoaderClient.h"
  29. #include "AuthenticationManager.h"
  30. #include "DataReference.h"
  31. #include "Logging.h"
  32. #include "NetworkBlobRegistry.h"
  33. #include "NetworkConnectionToWebProcess.h"
  34. #include "NetworkProcess.h"
  35. #include "NetworkProcessConnectionMessages.h"
  36. #include "NetworkResourceLoadParameters.h"
  37. #include "PlatformCertificateInfo.h"
  38. #include "RemoteNetworkingContext.h"
  39. #include "ShareableResource.h"
  40. #include "SharedMemory.h"
  41. #include "SynchronousNetworkLoaderClient.h"
  42. #include "WebCoreArgumentCoders.h"
  43. #include "WebErrors.h"
  44. #include "WebResourceLoaderMessages.h"
  45. #include <WebCore/NotImplemented.h>
  46. #include <WebCore/ResourceBuffer.h>
  47. #include <WebCore/ResourceHandle.h>
  48. #include <wtf/MainThread.h>
  49. using namespace WebCore;
  50. namespace WebKit {
  51. NetworkResourceLoader::NetworkResourceLoader(const NetworkResourceLoadParameters& parameters, NetworkConnectionToWebProcess* connection, PassRefPtr<Messages::NetworkConnectionToWebProcess::PerformSynchronousLoad::DelayedReply> reply)
  52. : m_bytesReceived(0)
  53. , m_handleConvertedToDownload(false)
  54. , m_identifier(parameters.identifier)
  55. , m_webPageID(parameters.webPageID)
  56. , m_webFrameID(parameters.webFrameID)
  57. , m_request(parameters.request)
  58. , m_priority(parameters.priority)
  59. , m_contentSniffingPolicy(parameters.contentSniffingPolicy)
  60. , m_allowStoredCredentials(parameters.allowStoredCredentials)
  61. , m_clientCredentialPolicy(parameters.clientCredentialPolicy)
  62. , m_inPrivateBrowsingMode(parameters.inPrivateBrowsingMode)
  63. , m_shouldClearReferrerOnHTTPSToHTTPRedirect(parameters.shouldClearReferrerOnHTTPSToHTTPRedirect)
  64. , m_isLoadingMainResource(parameters.isMainResource)
  65. , m_sandboxExtensionsAreConsumed(false)
  66. , m_connection(connection)
  67. {
  68. // Either this loader has both a webPageID and webFrameID, or it is not allowed to ask the client for authentication credentials.
  69. // FIXME: This is necessary because of the existence of EmptyFrameLoaderClient in WebCore.
  70. // Once bug 116233 is resolved, this ASSERT can just be "m_webPageID && m_webFrameID"
  71. ASSERT((m_webPageID && m_webFrameID) || m_clientCredentialPolicy == DoNotAskClientForAnyCredentials);
  72. for (size_t i = 0, count = parameters.requestBodySandboxExtensions.size(); i < count; ++i) {
  73. if (RefPtr<SandboxExtension> extension = SandboxExtension::create(parameters.requestBodySandboxExtensions[i]))
  74. m_requestBodySandboxExtensions.append(extension);
  75. }
  76. #if ENABLE(BLOB)
  77. if (m_request.httpBody()) {
  78. const Vector<FormDataElement>& elements = m_request.httpBody()->elements();
  79. for (size_t i = 0, count = elements.size(); i < count; ++i) {
  80. if (elements[i].m_type == FormDataElement::encodedBlob) {
  81. Vector<RefPtr<SandboxExtension>> blobElementExtensions = NetworkBlobRegistry::shared().sandboxExtensions(elements[i].m_url);
  82. m_requestBodySandboxExtensions.appendVector(blobElementExtensions);
  83. }
  84. }
  85. }
  86. if (m_request.url().protocolIs("blob")) {
  87. ASSERT(!SandboxExtension::create(parameters.resourceSandboxExtension));
  88. m_resourceSandboxExtensions = NetworkBlobRegistry::shared().sandboxExtensions(m_request.url());
  89. } else
  90. #endif
  91. if (RefPtr<SandboxExtension> resourceSandboxExtension = SandboxExtension::create(parameters.resourceSandboxExtension))
  92. m_resourceSandboxExtensions.append(resourceSandboxExtension);
  93. ASSERT(isMainThread());
  94. if (reply)
  95. m_networkLoaderClient = SynchronousNetworkLoaderClient::create(m_request, reply);
  96. else
  97. m_networkLoaderClient = AsynchronousNetworkLoaderClient::create();
  98. }
  99. NetworkResourceLoader::~NetworkResourceLoader()
  100. {
  101. ASSERT(isMainThread());
  102. ASSERT(!m_handle);
  103. ASSERT(!m_hostRecord);
  104. }
  105. bool NetworkResourceLoader::isSynchronous() const
  106. {
  107. return m_networkLoaderClient->isSynchronous();
  108. }
  109. void NetworkResourceLoader::start()
  110. {
  111. ASSERT(isMainThread());
  112. // Explicit ref() balanced by a deref() in NetworkResourceLoader::resourceHandleStopped()
  113. ref();
  114. // FIXME (NetworkProcess): Create RemoteNetworkingContext with actual settings.
  115. m_networkingContext = RemoteNetworkingContext::create(false, false, m_inPrivateBrowsingMode, m_shouldClearReferrerOnHTTPSToHTTPRedirect);
  116. consumeSandboxExtensions();
  117. // FIXME (NetworkProcess): Pass an actual value for defersLoading
  118. m_handle = ResourceHandle::create(m_networkingContext.get(), m_request, this, false /* defersLoading */, m_contentSniffingPolicy == SniffContent);
  119. }
  120. void NetworkResourceLoader::cleanup()
  121. {
  122. ASSERT(isMainThread());
  123. invalidateSandboxExtensions();
  124. if (FormData* formData = request().httpBody())
  125. formData->removeGeneratedFilesIfNeeded();
  126. // Tell the scheduler about this finished loader soon so it can start more network requests.
  127. NetworkProcess::shared().networkResourceLoadScheduler().scheduleRemoveLoader(this);
  128. if (m_handle) {
  129. // Explicit deref() balanced by a ref() in NetworkResourceLoader::start()
  130. // This might cause the NetworkResourceLoader to be destroyed and therefore we do it last.
  131. m_handle = 0;
  132. deref();
  133. }
  134. }
  135. void NetworkResourceLoader::didConvertHandleToDownload()
  136. {
  137. ASSERT(m_handle);
  138. m_handleConvertedToDownload = true;
  139. }
  140. void NetworkResourceLoader::abort()
  141. {
  142. ASSERT(isMainThread());
  143. if (m_handle && !m_handleConvertedToDownload)
  144. m_handle->cancel();
  145. cleanup();
  146. }
  147. void NetworkResourceLoader::didReceiveResponseAsync(ResourceHandle* handle, const ResourceResponse& response)
  148. {
  149. ASSERT_UNUSED(handle, handle == m_handle);
  150. // FIXME (NetworkProcess): Cache the response.
  151. if (FormData* formData = request().httpBody())
  152. formData->removeGeneratedFilesIfNeeded();
  153. m_networkLoaderClient->didReceiveResponse(this, response);
  154. // m_handle will be 0 if the request got aborted above.
  155. if (!m_handle)
  156. return;
  157. if (!m_isLoadingMainResource) {
  158. // For main resources, the web process is responsible for sending back a NetworkResourceLoader::ContinueDidReceiveResponse message.
  159. m_handle->continueDidReceiveResponse();
  160. }
  161. }
  162. void NetworkResourceLoader::didReceiveData(ResourceHandle*, const char* data, int length, int encodedDataLength)
  163. {
  164. // The NetworkProcess should never get a didReceiveData callback.
  165. // We should always be using didReceiveBuffer.
  166. ASSERT_NOT_REACHED();
  167. }
  168. void NetworkResourceLoader::didReceiveBuffer(ResourceHandle* handle, PassRefPtr<SharedBuffer> buffer, int encodedDataLength)
  169. {
  170. ASSERT_UNUSED(handle, handle == m_handle);
  171. // FIXME (NetworkProcess): For the memory cache we'll also need to cache the response data here.
  172. // Such buffering will need to be thread safe, as this callback is happening on a background thread.
  173. m_bytesReceived += buffer->size();
  174. m_networkLoaderClient->didReceiveBuffer(this, buffer.get(), encodedDataLength);
  175. }
  176. void NetworkResourceLoader::didFinishLoading(ResourceHandle* handle, double finishTime)
  177. {
  178. ASSERT_UNUSED(handle, handle == m_handle);
  179. m_networkLoaderClient->didFinishLoading(this, finishTime);
  180. cleanup();
  181. }
  182. void NetworkResourceLoader::didFail(ResourceHandle* handle, const ResourceError& error)
  183. {
  184. ASSERT_UNUSED(handle, handle == m_handle);
  185. m_networkLoaderClient->didFail(this, error);
  186. cleanup();
  187. }
  188. void NetworkResourceLoader::willSendRequestAsync(ResourceHandle* handle, const ResourceRequest& request, const ResourceResponse& redirectResponse)
  189. {
  190. ASSERT_UNUSED(handle, handle == m_handle);
  191. // We only expect to get the willSendRequest callback from ResourceHandle as the result of a redirect.
  192. ASSERT(!redirectResponse.isNull());
  193. ASSERT(isMainThread());
  194. ResourceRequest proposedRequest = request;
  195. m_suggestedRequestForWillSendRequest = request;
  196. m_networkLoaderClient->willSendRequest(this, proposedRequest, redirectResponse);
  197. }
  198. void NetworkResourceLoader::continueWillSendRequest(const ResourceRequest& newRequest)
  199. {
  200. m_suggestedRequestForWillSendRequest.updateFromDelegatePreservingOldHTTPBody(newRequest.nsURLRequest(DoNotUpdateHTTPBody));
  201. RunLoop::main()->dispatch(bind(&NetworkResourceLoadScheduler::receivedRedirect, &NetworkProcess::shared().networkResourceLoadScheduler(), this, m_suggestedRequestForWillSendRequest.url()));
  202. m_request = m_suggestedRequestForWillSendRequest;
  203. m_suggestedRequestForWillSendRequest = ResourceRequest();
  204. m_handle->continueWillSendRequest(m_request);
  205. if (m_request.isNull()) {
  206. m_handle->cancel();
  207. didFail(m_handle.get(), cancelledError(m_request));
  208. }
  209. }
  210. void NetworkResourceLoader::continueDidReceiveResponse()
  211. {
  212. // FIXME: Remove this check once BlobResourceHandle implements didReceiveResponseAsync correctly.
  213. // Currently, it does not wait for response, so the load is likely to finish before continueDidReceiveResponse.
  214. if (!m_handle)
  215. return;
  216. m_handle->continueDidReceiveResponse();
  217. }
  218. void NetworkResourceLoader::didSendData(ResourceHandle* handle, unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
  219. {
  220. ASSERT_UNUSED(handle, handle == m_handle);
  221. m_networkLoaderClient->didSendData(this, bytesSent, totalBytesToBeSent);
  222. }
  223. void NetworkResourceLoader::wasBlocked(ResourceHandle* handle)
  224. {
  225. ASSERT_UNUSED(handle, handle == m_handle);
  226. didFail(handle, WebKit::blockedError(request()));
  227. }
  228. void NetworkResourceLoader::cannotShowURL(ResourceHandle* handle)
  229. {
  230. ASSERT_UNUSED(handle, handle == m_handle);
  231. didFail(handle, WebKit::cannotShowURLError(request()));
  232. }
  233. bool NetworkResourceLoader::shouldUseCredentialStorage(ResourceHandle* handle)
  234. {
  235. ASSERT_UNUSED(handle, handle == m_handle || !m_handle); // m_handle will be 0 if called from ResourceHandle::start().
  236. // When the WebProcess is handling loading a client is consulted each time this shouldUseCredentialStorage question is asked.
  237. // In NetworkProcess mode we ask the WebProcess client up front once and then reuse the cached answer.
  238. // We still need this sync version, because ResourceHandle itself uses it internally, even when the delegate uses an async one.
  239. return m_allowStoredCredentials == AllowStoredCredentials;
  240. }
  241. void NetworkResourceLoader::shouldUseCredentialStorageAsync(ResourceHandle* handle)
  242. {
  243. ASSERT_UNUSED(handle, handle == m_handle);
  244. handle->continueShouldUseCredentialStorage(shouldUseCredentialStorage(handle));
  245. }
  246. void NetworkResourceLoader::didReceiveAuthenticationChallenge(ResourceHandle* handle, const AuthenticationChallenge& challenge)
  247. {
  248. ASSERT_UNUSED(handle, handle == m_handle);
  249. // FIXME (http://webkit.org/b/115291): Since we go straight to the UI process for authentication we don't get WebCore's
  250. // cross-origin check before asking the client for credentials.
  251. // Therefore we are too permissive in the case where the ClientCredentialPolicy is DoNotAskClientForCrossOriginCredentials.
  252. if (m_clientCredentialPolicy == DoNotAskClientForAnyCredentials) {
  253. challenge.authenticationClient()->receivedRequestToContinueWithoutCredential(challenge);
  254. return;
  255. }
  256. NetworkProcess::shared().authenticationManager().didReceiveAuthenticationChallenge(m_webPageID, m_webFrameID, challenge);
  257. }
  258. void NetworkResourceLoader::didCancelAuthenticationChallenge(ResourceHandle* handle, const AuthenticationChallenge& challenge)
  259. {
  260. ASSERT_UNUSED(handle, handle == m_handle);
  261. // This function is probably not needed (see <rdar://problem/8960124>).
  262. notImplemented();
  263. }
  264. CoreIPC::Connection* NetworkResourceLoader::messageSenderConnection()
  265. {
  266. return connectionToWebProcess()->connection();
  267. }
  268. void NetworkResourceLoader::consumeSandboxExtensions()
  269. {
  270. for (size_t i = 0, count = m_requestBodySandboxExtensions.size(); i < count; ++i)
  271. m_requestBodySandboxExtensions[i]->consume();
  272. for (size_t i = 0, count = m_resourceSandboxExtensions.size(); i < count; ++i)
  273. m_resourceSandboxExtensions[i]->consume();
  274. m_sandboxExtensionsAreConsumed = true;
  275. }
  276. void NetworkResourceLoader::invalidateSandboxExtensions()
  277. {
  278. if (m_sandboxExtensionsAreConsumed) {
  279. for (size_t i = 0, count = m_requestBodySandboxExtensions.size(); i < count; ++i)
  280. m_requestBodySandboxExtensions[i]->revoke();
  281. for (size_t i = 0, count = m_resourceSandboxExtensions.size(); i < count; ++i)
  282. m_resourceSandboxExtensions[i]->revoke();
  283. }
  284. m_requestBodySandboxExtensions.clear();
  285. m_resourceSandboxExtensions.clear();
  286. m_sandboxExtensionsAreConsumed = false;
  287. }
  288. #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
  289. void NetworkResourceLoader::canAuthenticateAgainstProtectionSpaceAsync(ResourceHandle* handle, const ProtectionSpace& protectionSpace)
  290. {
  291. ASSERT(isMainThread());
  292. ASSERT_UNUSED(handle, handle == m_handle);
  293. m_networkLoaderClient->canAuthenticateAgainstProtectionSpace(this, protectionSpace);
  294. }
  295. void NetworkResourceLoader::continueCanAuthenticateAgainstProtectionSpace(bool result)
  296. {
  297. m_handle->continueCanAuthenticateAgainstProtectionSpace(result);
  298. }
  299. #endif
  300. #if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
  301. bool NetworkResourceLoader::supportsDataArray()
  302. {
  303. notImplemented();
  304. return false;
  305. }
  306. void NetworkResourceLoader::didReceiveDataArray(ResourceHandle*, CFArrayRef)
  307. {
  308. ASSERT_NOT_REACHED();
  309. notImplemented();
  310. }
  311. #endif
  312. #if PLATFORM(MAC)
  313. void NetworkResourceLoader::willStopBufferingData(ResourceHandle*, const char*, int)
  314. {
  315. notImplemented();
  316. }
  317. #endif // PLATFORM(MAC)
  318. } // namespace WebKit
  319. #endif // ENABLE(NETWORK_PROCESS)