/src/3rdparty/webkit/Source/WebCore/loader/ResourceLoader.cpp

https://bitbucket.org/ultra_iter/qt-vtl · C++ · 515 lines · 349 code · 89 blank · 77 comment · 56 complexity · dfa9b73f332d74b56df7ed289a86b3bd MD5 · raw file

  1. /*
  2. * Copyright (C) 2006, 2007, 2010, 2011 Apple Inc. All rights reserved.
  3. * (C) 2007 Graham Dennis (graham.dennis@gmail.com)
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. *
  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. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
  15. * its contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
  19. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. */
  29. #include "config.h"
  30. #include "ResourceLoader.h"
  31. #include "ApplicationCacheHost.h"
  32. #include "DocumentLoader.h"
  33. #include "FileStreamProxy.h"
  34. #include "Frame.h"
  35. #include "FrameLoader.h"
  36. #include "FrameLoaderClient.h"
  37. #include "InspectorInstrumentation.h"
  38. #include "Page.h"
  39. #include "ProgressTracker.h"
  40. #include "ResourceError.h"
  41. #include "ResourceHandle.h"
  42. #include "ResourceLoadScheduler.h"
  43. #include "Settings.h"
  44. #include "SharedBuffer.h"
  45. namespace WebCore {
  46. PassRefPtr<SharedBuffer> ResourceLoader::resourceData()
  47. {
  48. if (m_resourceData)
  49. return m_resourceData;
  50. if (ResourceHandle::supportsBufferedData() && m_handle)
  51. return m_handle->bufferedData();
  52. return 0;
  53. }
  54. ResourceLoader::ResourceLoader(Frame* frame, bool sendResourceLoadCallbacks, bool shouldContentSniff)
  55. : m_frame(frame)
  56. , m_documentLoader(frame->loader()->activeDocumentLoader())
  57. , m_identifier(0)
  58. , m_reachedTerminalState(false)
  59. , m_cancelled(false)
  60. , m_calledDidFinishLoad(false)
  61. , m_sendResourceLoadCallbacks(sendResourceLoadCallbacks)
  62. , m_shouldContentSniff(shouldContentSniff)
  63. , m_shouldBufferData(true)
  64. , m_defersLoading(frame->page()->defersLoading())
  65. {
  66. }
  67. ResourceLoader::~ResourceLoader()
  68. {
  69. ASSERT(m_reachedTerminalState);
  70. }
  71. void ResourceLoader::releaseResources()
  72. {
  73. ASSERT(!m_reachedTerminalState);
  74. // It's possible that when we release the handle, it will be
  75. // deallocated and release the last reference to this object.
  76. // We need to retain to avoid accessing the object after it
  77. // has been deallocated and also to avoid reentering this method.
  78. RefPtr<ResourceLoader> protector(this);
  79. m_frame = 0;
  80. m_documentLoader = 0;
  81. // We need to set reachedTerminalState to true before we release
  82. // the resources to prevent a double dealloc of WebView <rdar://problem/4372628>
  83. m_reachedTerminalState = true;
  84. m_identifier = 0;
  85. resourceLoadScheduler()->remove(this);
  86. if (m_handle) {
  87. // Clear out the ResourceHandle's client so that it doesn't try to call
  88. // us back after we release it, unless it has been replaced by someone else.
  89. if (m_handle->client() == this)
  90. m_handle->setClient(0);
  91. m_handle = 0;
  92. }
  93. m_resourceData = 0;
  94. m_deferredRequest = ResourceRequest();
  95. }
  96. bool ResourceLoader::init(const ResourceRequest& r)
  97. {
  98. ASSERT(!m_handle);
  99. ASSERT(m_request.isNull());
  100. ASSERT(m_deferredRequest.isNull());
  101. ASSERT(!m_documentLoader->isSubstituteLoadPending(this));
  102. ResourceRequest clientRequest(r);
  103. // https://bugs.webkit.org/show_bug.cgi?id=26391
  104. // The various plug-in implementations call directly to ResourceLoader::load() instead of piping requests
  105. // through FrameLoader. As a result, they miss the FrameLoader::addExtraFieldsToRequest() step which sets
  106. // up the 1st party for cookies URL. Until plug-in implementations can be reigned in to pipe through that
  107. // method, we need to make sure there is always a 1st party for cookies set.
  108. if (clientRequest.firstPartyForCookies().isNull()) {
  109. if (Document* document = m_frame->document())
  110. clientRequest.setFirstPartyForCookies(document->firstPartyForCookies());
  111. }
  112. willSendRequest(clientRequest, ResourceResponse());
  113. if (clientRequest.isNull()) {
  114. didFail(frameLoader()->cancelledError(m_request));
  115. return false;
  116. }
  117. m_request = clientRequest;
  118. return true;
  119. }
  120. void ResourceLoader::start()
  121. {
  122. ASSERT(!m_handle);
  123. ASSERT(!m_request.isNull());
  124. ASSERT(m_deferredRequest.isNull());
  125. #if ENABLE(WEB_ARCHIVE)
  126. if (m_documentLoader->scheduleArchiveLoad(this, m_request, m_request.url()))
  127. return;
  128. #endif
  129. #if ENABLE(OFFLINE_WEB_APPLICATIONS)
  130. if (m_documentLoader->applicationCacheHost()->maybeLoadResource(this, m_request, m_request.url()))
  131. return;
  132. #endif
  133. if (m_defersLoading) {
  134. m_deferredRequest = m_request;
  135. return;
  136. }
  137. if (!m_reachedTerminalState)
  138. m_handle = ResourceHandle::create(m_frame->loader()->networkingContext(), m_request, this, m_defersLoading, m_shouldContentSniff);
  139. }
  140. void ResourceLoader::setDefersLoading(bool defers)
  141. {
  142. m_defersLoading = defers;
  143. if (m_handle)
  144. m_handle->setDefersLoading(defers);
  145. if (!defers && !m_deferredRequest.isNull()) {
  146. m_request = m_deferredRequest;
  147. m_deferredRequest = ResourceRequest();
  148. start();
  149. }
  150. }
  151. FrameLoader* ResourceLoader::frameLoader() const
  152. {
  153. if (!m_frame)
  154. return 0;
  155. return m_frame->loader();
  156. }
  157. void ResourceLoader::setShouldBufferData(bool shouldBufferData)
  158. {
  159. m_shouldBufferData = shouldBufferData;
  160. // Reset any already buffered data
  161. if (!m_shouldBufferData)
  162. m_resourceData = 0;
  163. }
  164. void ResourceLoader::addData(const char* data, int length, bool allAtOnce)
  165. {
  166. if (!m_shouldBufferData)
  167. return;
  168. if (allAtOnce) {
  169. m_resourceData = SharedBuffer::create(data, length);
  170. return;
  171. }
  172. if (ResourceHandle::supportsBufferedData()) {
  173. // Buffer data only if the connection has handed us the data because is has stopped buffering it.
  174. if (m_resourceData)
  175. m_resourceData->append(data, length);
  176. } else {
  177. if (!m_resourceData)
  178. m_resourceData = SharedBuffer::create(data, length);
  179. else
  180. m_resourceData->append(data, length);
  181. }
  182. }
  183. void ResourceLoader::clearResourceData()
  184. {
  185. if (m_resourceData)
  186. m_resourceData->clear();
  187. }
  188. void ResourceLoader::willSendRequest(ResourceRequest& request, const ResourceResponse& redirectResponse)
  189. {
  190. // Protect this in this delegate method since the additional processing can do
  191. // anything including possibly derefing this; one example of this is Radar 3266216.
  192. RefPtr<ResourceLoader> protector(this);
  193. ASSERT(!m_reachedTerminalState);
  194. if (m_sendResourceLoadCallbacks) {
  195. if (!m_identifier) {
  196. m_identifier = m_frame->page()->progress()->createUniqueIdentifier();
  197. frameLoader()->notifier()->assignIdentifierToInitialRequest(m_identifier, documentLoader(), request);
  198. }
  199. frameLoader()->notifier()->willSendRequest(this, request, redirectResponse);
  200. }
  201. if (!redirectResponse.isNull())
  202. resourceLoadScheduler()->crossOriginRedirectReceived(this, request.url());
  203. m_request = request;
  204. }
  205. void ResourceLoader::didSendData(unsigned long long, unsigned long long)
  206. {
  207. }
  208. void ResourceLoader::didReceiveResponse(const ResourceResponse& r)
  209. {
  210. ASSERT(!m_reachedTerminalState);
  211. // Protect this in this delegate method since the additional processing can do
  212. // anything including possibly derefing this; one example of this is Radar 3266216.
  213. RefPtr<ResourceLoader> protector(this);
  214. m_response = r;
  215. if (FormData* data = m_request.httpBody())
  216. data->removeGeneratedFilesIfNeeded();
  217. if (m_sendResourceLoadCallbacks)
  218. frameLoader()->notifier()->didReceiveResponse(this, m_response);
  219. }
  220. void ResourceLoader::didReceiveData(const char* data, int length, long long encodedDataLength, bool allAtOnce)
  221. {
  222. // The following assertions are not quite valid here, since a subclass
  223. // might override didReceiveData in a way that invalidates them. This
  224. // happens with the steps listed in 3266216
  225. // ASSERT(con == connection);
  226. // ASSERT(!m_reachedTerminalState);
  227. // Protect this in this delegate method since the additional processing can do
  228. // anything including possibly derefing this; one example of this is Radar 3266216.
  229. RefPtr<ResourceLoader> protector(this);
  230. addData(data, length, allAtOnce);
  231. // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
  232. // However, with today's computers and networking speeds, this won't happen in practice.
  233. // Could be an issue with a giant local file.
  234. if (m_sendResourceLoadCallbacks && m_frame)
  235. frameLoader()->notifier()->didReceiveData(this, data, length, static_cast<int>(encodedDataLength));
  236. }
  237. void ResourceLoader::willStopBufferingData(const char* data, int length)
  238. {
  239. if (!m_shouldBufferData)
  240. return;
  241. ASSERT(!m_resourceData);
  242. m_resourceData = SharedBuffer::create(data, length);
  243. }
  244. void ResourceLoader::didFinishLoading(double finishTime)
  245. {
  246. // If load has been cancelled after finishing (which could happen with a
  247. // JavaScript that changes the window location), do nothing.
  248. if (m_cancelled)
  249. return;
  250. ASSERT(!m_reachedTerminalState);
  251. didFinishLoadingOnePart(finishTime);
  252. releaseResources();
  253. }
  254. void ResourceLoader::didFinishLoadingOnePart(double finishTime)
  255. {
  256. if (m_cancelled)
  257. return;
  258. ASSERT(!m_reachedTerminalState);
  259. if (m_calledDidFinishLoad)
  260. return;
  261. m_calledDidFinishLoad = true;
  262. if (m_sendResourceLoadCallbacks)
  263. frameLoader()->notifier()->didFinishLoad(this, finishTime);
  264. }
  265. void ResourceLoader::didFail(const ResourceError& error)
  266. {
  267. if (m_cancelled)
  268. return;
  269. ASSERT(!m_reachedTerminalState);
  270. // Protect this in this delegate method since the additional processing can do
  271. // anything including possibly derefing this; one example of this is Radar 3266216.
  272. RefPtr<ResourceLoader> protector(this);
  273. if (FormData* data = m_request.httpBody())
  274. data->removeGeneratedFilesIfNeeded();
  275. if (m_sendResourceLoadCallbacks && !m_calledDidFinishLoad)
  276. frameLoader()->notifier()->didFailToLoad(this, error);
  277. releaseResources();
  278. }
  279. void ResourceLoader::didCancel(const ResourceError& error)
  280. {
  281. ASSERT(!m_cancelled);
  282. ASSERT(!m_reachedTerminalState);
  283. if (FormData* data = m_request.httpBody())
  284. data->removeGeneratedFilesIfNeeded();
  285. // This flag prevents bad behavior when loads that finish cause the
  286. // load itself to be cancelled (which could happen with a javascript that
  287. // changes the window location). This is used to prevent both the body
  288. // of this method and the body of connectionDidFinishLoading: running
  289. // for a single delegate. Canceling wins.
  290. m_cancelled = true;
  291. if (m_handle)
  292. m_handle->clearAuthentication();
  293. m_documentLoader->cancelPendingSubstituteLoad(this);
  294. if (m_handle) {
  295. m_handle->cancel();
  296. m_handle = 0;
  297. }
  298. if (m_sendResourceLoadCallbacks && m_identifier && !m_calledDidFinishLoad)
  299. frameLoader()->notifier()->didFailToLoad(this, error);
  300. releaseResources();
  301. }
  302. void ResourceLoader::cancel()
  303. {
  304. cancel(ResourceError());
  305. }
  306. void ResourceLoader::cancel(const ResourceError& error)
  307. {
  308. if (m_reachedTerminalState)
  309. return;
  310. if (!error.isNull())
  311. didCancel(error);
  312. else
  313. didCancel(cancelledError());
  314. }
  315. const ResourceResponse& ResourceLoader::response() const
  316. {
  317. return m_response;
  318. }
  319. ResourceError ResourceLoader::cancelledError()
  320. {
  321. return frameLoader()->cancelledError(m_request);
  322. }
  323. ResourceError ResourceLoader::blockedError()
  324. {
  325. return frameLoader()->blockedError(m_request);
  326. }
  327. ResourceError ResourceLoader::cannotShowURLError()
  328. {
  329. return frameLoader()->cannotShowURLError(m_request);
  330. }
  331. void ResourceLoader::willSendRequest(ResourceHandle*, ResourceRequest& request, const ResourceResponse& redirectResponse)
  332. {
  333. #if ENABLE(OFFLINE_WEB_APPLICATIONS)
  334. if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForRedirect(this, request, redirectResponse))
  335. return;
  336. #endif
  337. willSendRequest(request, redirectResponse);
  338. }
  339. void ResourceLoader::didSendData(ResourceHandle*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
  340. {
  341. didSendData(bytesSent, totalBytesToBeSent);
  342. }
  343. void ResourceLoader::didReceiveResponse(ResourceHandle*, const ResourceResponse& response)
  344. {
  345. #if ENABLE(OFFLINE_WEB_APPLICATIONS)
  346. if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForResponse(this, response))
  347. return;
  348. #endif
  349. didReceiveResponse(response);
  350. }
  351. void ResourceLoader::didReceiveData(ResourceHandle*, const char* data, int length, int encodedDataLength)
  352. {
  353. InspectorInstrumentationCookie cookie = InspectorInstrumentation::willReceiveResourceData(m_frame.get(), identifier());
  354. didReceiveData(data, length, encodedDataLength, false);
  355. InspectorInstrumentation::didReceiveResourceData(cookie);
  356. }
  357. void ResourceLoader::didFinishLoading(ResourceHandle*, double finishTime)
  358. {
  359. didFinishLoading(finishTime);
  360. }
  361. void ResourceLoader::didFail(ResourceHandle*, const ResourceError& error)
  362. {
  363. #if ENABLE(OFFLINE_WEB_APPLICATIONS)
  364. if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForError(this, error))
  365. return;
  366. #endif
  367. didFail(error);
  368. }
  369. void ResourceLoader::wasBlocked(ResourceHandle*)
  370. {
  371. didFail(blockedError());
  372. }
  373. void ResourceLoader::cannotShowURL(ResourceHandle*)
  374. {
  375. didFail(cannotShowURLError());
  376. }
  377. bool ResourceLoader::shouldUseCredentialStorage()
  378. {
  379. RefPtr<ResourceLoader> protector(this);
  380. return frameLoader()->shouldUseCredentialStorage(this);
  381. }
  382. void ResourceLoader::didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge)
  383. {
  384. // Protect this in this delegate method since the additional processing can do
  385. // anything including possibly derefing this; one example of this is Radar 3266216.
  386. RefPtr<ResourceLoader> protector(this);
  387. frameLoader()->notifier()->didReceiveAuthenticationChallenge(this, challenge);
  388. }
  389. void ResourceLoader::didCancelAuthenticationChallenge(const AuthenticationChallenge& challenge)
  390. {
  391. // Protect this in this delegate method since the additional processing can do
  392. // anything including possibly derefing this; one example of this is Radar 3266216.
  393. RefPtr<ResourceLoader> protector(this);
  394. frameLoader()->notifier()->didCancelAuthenticationChallenge(this, challenge);
  395. }
  396. #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
  397. bool ResourceLoader::canAuthenticateAgainstProtectionSpace(const ProtectionSpace& protectionSpace)
  398. {
  399. RefPtr<ResourceLoader> protector(this);
  400. return frameLoader()->canAuthenticateAgainstProtectionSpace(this, protectionSpace);
  401. }
  402. #endif
  403. void ResourceLoader::receivedCancellation(const AuthenticationChallenge&)
  404. {
  405. cancel();
  406. }
  407. void ResourceLoader::willCacheResponse(ResourceHandle*, CacheStoragePolicy& policy)
  408. {
  409. // <rdar://problem/7249553> - There are reports of crashes with this method being called
  410. // with a null m_frame->settings(), which can only happen if the frame doesn't have a page.
  411. // Sadly we have no reproducible cases of this.
  412. // We think that any frame without a page shouldn't have any loads happening in it, yet
  413. // there is at least one code path where that is not true.
  414. ASSERT(m_frame->settings());
  415. // When in private browsing mode, prevent caching to disk
  416. if (policy == StorageAllowed && m_frame->settings() && m_frame->settings()->privateBrowsingEnabled())
  417. policy = StorageAllowedInMemoryOnly;
  418. }
  419. #if ENABLE(BLOB)
  420. AsyncFileStream* ResourceLoader::createAsyncFileStream(FileStreamClient* client)
  421. {
  422. // It is OK to simply return a pointer since FileStreamProxy::create adds an extra ref.
  423. return FileStreamProxy::create(m_frame->document()->scriptExecutionContext(), client).get();
  424. }
  425. #endif
  426. }