void MainResourceLoader::notifyFinished(CachedResource* resource) { ASSERT_UNUSED(resource, m_resource == resource); if (!m_resource || (!m_resource->errorOccurred() && !m_resource->wasCanceled())) { didFinishLoading(m_resource->loadFinishTime()); return; } #if PLATFORM(MAC) && !PLATFORM(IOS) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 if (m_filter) { wkFilterRelease(m_filter); m_filter = 0; } #endif const ResourceError& error = m_resource->resourceError(); if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForMainError(request(), error)) return; // There is a bug in CFNetwork where callbacks can be dispatched even when loads are deferred. // See <rdar://problem/6304600> for more details. #if !USE(CF) ASSERT(!defersLoading()); #endif receivedError(error); }
void MainResourceLoader::notifyFinished(CachedResource* resource) { ASSERT_UNUSED(resource, m_resource == resource); ASSERT(m_resource); if (!m_resource->errorOccurred() && !m_resource->wasCanceled()) { didFinishLoading(m_resource->loadFinishTime()); return; } if (m_documentLoader->request().cachePolicy() == ReturnCacheDataDontLoad && !m_resource->wasCanceled()) { frameLoader()->retryAfterFailedCacheOnlyMainResourceLoad(); return; } #if USE(CONTENT_FILTERING) if (m_filter) { wkFilterRelease(m_filter); m_filter = 0; } #endif const ResourceError& error = m_resource->resourceError(); if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForMainError(request(), error)) return; // There is a bug in CFNetwork where callbacks can be dispatched even when loads are deferred. // See <rdar://problem/6304600> for more details. #if !USE(CF) ASSERT(!defersLoading()); #endif receivedError(error); }
void ResourceLoader::requestSynchronously() { OwnPtr<WebKit::WebURLLoader> loader = adoptPtr(WebKit::Platform::current()->createURLLoader()); ASSERT(loader); RELEASE_ASSERT(m_connectionState == ConnectionStateNew); m_connectionState = ConnectionStateStarted; WebKit::WrappedResourceRequest requestIn(m_request); requestIn.setAllowStoredCredentials(m_options.allowCredentials == AllowStoredCredentials); WebKit::WebURLResponse responseOut; responseOut.initialize(); WebKit::WebURLError errorOut; WebKit::WebData dataOut; loader->loadSynchronously(requestIn, responseOut, errorOut, dataOut); if (errorOut.reason) { didFail(0, errorOut); return; } didReceiveResponse(0, responseOut); RefPtr<ResourceLoadInfo> resourceLoadInfo = responseOut.toResourceResponse().resourceLoadInfo(); m_host->didReceiveData(m_resource, dataOut.data(), dataOut.size(), resourceLoadInfo ? resourceLoadInfo->encodedDataLength : -1, m_options); m_resource->setResourceBuffer(dataOut); didFinishLoading(0, responseOut.responseTime()); }
void MainResourceLoader::notifyFinished(CachedResource* resource) { ASSERT_UNUSED(resource, m_resource == resource); ASSERT(m_resource); if (!m_resource->errorOccurred() && !m_resource->wasCanceled()) { didFinishLoading(m_resource->loadFinishTime()); return; } // FIXME: we should fix the design to eliminate the need for a platform ifdef here #if !PLATFORM(CHROMIUM) if (m_documentLoader->request().cachePolicy() == ReturnCacheDataDontLoad && !m_resource->wasCanceled()) { frameLoader()->retryAfterFailedCacheOnlyMainResourceLoad(); return; } #endif const ResourceError& error = m_resource->resourceError(); if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForMainError(request(), error)) return; // There is a bug in CFNetwork where callbacks can be dispatched even when loads are deferred. // See <rdar://problem/6304600> for more details. #if !USE(CF) ASSERT(!defersLoading()); #endif receivedError(error); }
void ResourceLoader::requestSynchronously() { OwnPtr<blink::WebURLLoader> loader = adoptPtr(blink::Platform::current()->createURLLoader()); ASSERT(loader); RefPtr<ResourceLoader> protect(this); RefPtr<ResourceLoaderHost> protectHost(m_host); ResourcePtr<Resource> protectResource(m_resource); RELEASE_ASSERT(m_connectionState == ConnectionStateNew); m_connectionState = ConnectionStateStarted; blink::WrappedResourceRequest requestIn(m_request); requestIn.setAllowStoredCredentials(m_options.allowCredentials == AllowStoredCredentials); blink::WebURLResponse responseOut; responseOut.initialize(); blink::WebURLError errorOut; blink::WebData dataOut; loader->loadSynchronously(requestIn, responseOut, errorOut, dataOut); if (errorOut.reason) { didFail(0, errorOut); return; } didReceiveResponse(0, responseOut); if (m_state == Terminated) return; RefPtr<ResourceLoadInfo> resourceLoadInfo = responseOut.toResourceResponse().resourceLoadInfo(); int64 encodedDataLength = resourceLoadInfo ? resourceLoadInfo->encodedDataLength : blink::WebURLLoaderClient::kUnknownEncodedDataLength; m_host->didReceiveData(m_resource, dataOut.data(), dataOut.size(), encodedDataLength); m_resource->setResourceBuffer(dataOut); didFinishLoading(0, monotonicallyIncreasingTime(), encodedDataLength); }
void ResourceLoader::didFinishLoading(ResourceHandle*, double finishTime) { if (!fastMallocSize(documentLoader()->applicationCacheHost())) CRASH(); if (!fastMallocSize(documentLoader()->frame())) CRASH(); didFinishLoading(finishTime); }
void DocumentThreadableLoader::notifyFinished(CachedResource* resource) { ASSERT(m_client); ASSERT_UNUSED(resource, resource == m_resource); if (m_resource->errorOccurred()) didFail(m_resource->identifier(), m_resource->resourceError()); else didFinishLoading(m_resource->identifier(), m_resource->loadFinishTime()); }
void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, SecurityCheckPolicy securityCheck) { // Any credential should have been removed from the cross-site requests. const KURL& requestURL = request.url(); ASSERT(m_sameOriginRequest || requestURL.user().isEmpty()); ASSERT(m_sameOriginRequest || requestURL.pass().isEmpty()); if (m_async) { // Don't sniff content or send load callbacks for the preflight request. bool sendLoadCallbacks = m_options.sendLoadCallbacks && !m_actualRequest; bool sniffContent = m_options.sniffContent && !m_actualRequest; // Keep buffering the data for the preflight request. bool shouldBufferData = m_options.shouldBufferData || m_actualRequest; // Clear the loader so that any callbacks from SubresourceLoader::create will not have the old loader. m_loader = 0; m_loader = resourceLoadScheduler()->scheduleSubresourceLoad(m_document->frame(), this, request, ResourceLoadPriorityMedium, securityCheck, sendLoadCallbacks, sniffContent, m_optionalOutgoingReferrer, shouldBufferData); return; } // FIXME: ThreadableLoaderOptions.sniffContent is not supported for synchronous requests. StoredCredentials storedCredentials = m_options.allowCredentials ? AllowStoredCredentials : DoNotAllowStoredCredentials; Vector<char> data; ResourceError error; ResourceResponse response; unsigned long identifier = std::numeric_limits<unsigned long>::max(); if (m_document->frame()) identifier = m_document->frame()->loader()->loadResourceSynchronously(request, storedCredentials, error, response, data); // No exception for file:/// resources, see <rdar://problem/4962298>. // Also, if we have an HTTP response, then it wasn't a network error in fact. if (!error.isNull() && !requestURL.isLocalFile() && response.httpStatusCode() <= 0) { m_client->didFail(error); return; } // FIXME: FrameLoader::loadSynchronously() does not tell us whether a redirect happened or not, so we guess by comparing the // request and response URLs. This isn't a perfect test though, since a server can serve a redirect to the same URL that was // requested. Also comparing the request and response URLs as strings will fail if the requestURL still has its credentials. if (requestURL != response.url() && !isAllowedRedirect(response.url())) { m_client->didFailRedirectCheck(); return; } didReceiveResponse(0, response); const char* bytes = static_cast<const char*>(data.data()); int len = static_cast<int>(data.size()); didReceiveData(0, bytes, len); didFinishLoading(identifier, 0.0); }
void DocumentThreadableLoader::notifyFinished(Resource* resource) { ASSERT(m_client); ASSERT(resource == this->resource()); m_timeoutTimer.stop(); if (resource->errorOccurred()) m_client->didFail(resource->resourceError()); else didFinishLoading(resource->identifier(), resource->loadFinishTime()); }
void DocumentThreadableLoader::notifyFinished(CachedResource* resource) { ASSERT(m_client); ASSERT_UNUSED(resource, resource == m_resource); if (m_resource && (m_resource->errorOccurred() || m_resource->wasCanceled())) { ResourceError error("Network Request Failed", 0, m_resource->url(), "Resource failed to load"); if (m_resource->wasCanceled()) error.setIsCancellation(true); didFail(error); } else didFinishLoading(m_resource->identifier(), m_resource->loadFinishTime()); }
void HTMLImportLoader::setState(State state) { if (m_state == state) return; m_state = state; if (m_state == StateParsed || m_state == StateError || m_state == StateWritten) { if (m_document) m_document->cancelParsing(); } // Since DocumentWriter::end() can let setState() reenter, we shouldn't refer to m_state here. if (state == StateLoaded || state == StateError) didFinishLoading(); }
void HTMLImportLoader::setState(State state) { if (m_state == state) return; m_state = state; if (m_state == StateParsed || m_state == StateError || m_state == StateWritten) { if (RefPtrWillBeRawPtr<DocumentWriter> writer = m_writer.release()) writer->end(); } // Since DocumentWriter::end() can let setState() reenter, we shouldn't refer to m_state here. if (state == StateLoaded || state == StateError) didFinishLoading(); }
void Downloader::performDownload() { long repCode = -1; CURLcode res = CURLE_OK; res = curl_easy_perform(m_curl); if ( CURLE_OK == res ) { curl_easy_getinfo(m_curl, CURLINFO_RESPONSE_CODE, &repCode); //char buf[8]; //curl_easy_getinfo(m_curl, CURLINFO_CONTENT_TYPE, &buf); } didReceiveResponse(repCode); didFinishLoading(); }
void ResourceLoader::deliverResponseAndData(const ResourceResponse& response, RefPtr<SharedBuffer>&& buffer) { Ref<ResourceLoader> protect(*this); didReceiveResponse(response); if (reachedTerminalState()) return; if (buffer) { unsigned size = buffer->size(); didReceiveBuffer(buffer.release(), size, DataPayloadWholeResource); if (reachedTerminalState()) return; } didFinishLoading(0); }
void ResourceLoader::requestSynchronously() { OwnPtr<WebURLLoader> loader = adoptPtr(Platform::current()->createURLLoader()); ASSERT(loader); // downloadToFile is not supported for synchronous requests. ASSERT(!m_request.downloadToFile()); ResourcePtr<Resource> protectResource(m_resource); RELEASE_ASSERT(m_connectionState == ConnectionStateNew); m_connectionState = ConnectionStateStarted; WrappedResourceRequest requestIn(m_request); WebURLResponse responseOut; responseOut.initialize(); WebURLError errorOut; WebData dataOut; loader->loadSynchronously(requestIn, responseOut, errorOut, dataOut); if (errorOut.reason) { if (m_state == Terminated) { // A message dispatched while synchronously fetching the resource // can bring about the cancellation of this load. ASSERT(!m_resource); return; } didFail(0, errorOut); return; } didReceiveResponse(0, responseOut); if (m_state == Terminated) return; RefPtr<ResourceLoadInfo> resourceLoadInfo = responseOut.toResourceResponse().resourceLoadInfo(); int64_t encodedDataLength = resourceLoadInfo ? resourceLoadInfo->encodedDataLength : WebURLLoaderClient::kUnknownEncodedDataLength; // Follow the async case convention of not calling didReceiveData or // appending data to m_resource if the response body is empty. Copying the // empty buffer is a noop in most cases, but is destructive in the case of // a 304, where it will overwrite the cached data we should be reusing. if (dataOut.size()) { m_fetcher->didReceiveData(m_resource, dataOut.data(), dataOut.size(), encodedDataLength); m_resource->setResourceBuffer(dataOut); } didFinishLoading(0, monotonicallyIncreasingTime(), encodedDataLength); }
void HTMLImportLoader::setState(State state) { if (m_state == state) return; m_state = state; if (m_state == StateParsed || m_state == StateError || m_state == StateWritten) { if (DocumentWriter* writer = m_writer.release()) writer->end(); } // Since DocumentWriter::end() can let setState() reenter, we shouldn't refer to m_state here. if (state == StateLoaded) m_document->setReadyState(Document::Complete); if (state == StateLoaded || state == StateError) didFinishLoading(); }
void ResourceLoader::requestSynchronously(const ResourceRequest& request) { // downloadToFile is not supported for synchronous requests. DCHECK(!request.downloadToFile()); DCHECK(m_loader); DCHECK_EQ(request.priority(), ResourceLoadPriorityHighest); WrappedResourceRequest requestIn(request); WebURLResponse responseOut; WebURLError errorOut; WebData dataOut; int64_t encodedDataLength = WebURLLoaderClient::kUnknownEncodedDataLength; int64_t encodedBodyLength = 0; m_loader->loadSynchronously(requestIn, responseOut, errorOut, dataOut, encodedDataLength, encodedBodyLength); // A message dispatched while synchronously fetching the resource // can bring about the cancellation of this load. if (!m_loader) return; if (errorOut.reason) { didFail(errorOut, encodedDataLength, encodedBodyLength); return; } didReceiveResponse(responseOut); if (!m_loader) return; DCHECK_GE(responseOut.toResourceResponse().encodedBodyLength(), 0); // Follow the async case convention of not calling didReceiveData or // appending data to m_resource if the response body is empty. Copying the // empty buffer is a noop in most cases, but is destructive in the case of // a 304, where it will overwrite the cached data we should be reusing. if (dataOut.size()) { m_fetcher->didReceiveData(m_resource.get(), dataOut.data(), dataOut.size()); m_resource->setResourceBuffer(dataOut); } didFinishLoading(monotonicallyIncreasingTime(), encodedDataLength, encodedBodyLength); }
void ResourceLoader::requestSynchronously() { OwnPtr<WebURLLoader> loader = adoptPtr(Platform::current()->createURLLoader()); ASSERT(loader); // downloadToFile is not supported for synchronous requests. ASSERT(!m_request.downloadToFile()); ResourcePtr<Resource> protectResource(m_resource); RELEASE_ASSERT(m_connectionState == ConnectionStateNew); m_connectionState = ConnectionStateStarted; WrappedResourceRequest requestIn(m_request); WebURLResponse responseOut; responseOut.initialize(); WebURLError errorOut; WebData dataOut; loader->loadSynchronously(requestIn, responseOut, errorOut, dataOut); if (errorOut.reason) { if (m_state == Terminated) { // A message dispatched while synchronously fetching the resource // can bring about the cancellation of this load. ASSERT(!m_resource); return; } didFail(0, errorOut); return; } didReceiveResponse(0, responseOut); if (m_state == Terminated) return; RefPtr<ResourceLoadInfo> resourceLoadInfo = responseOut.toResourceResponse().resourceLoadInfo(); int64_t encodedDataLength = resourceLoadInfo ? resourceLoadInfo->encodedDataLength : WebURLLoaderClient::kUnknownEncodedDataLength; m_fetcher->didReceiveData(m_resource, dataOut.data(), dataOut.size(), encodedDataLength); m_resource->setResourceBuffer(dataOut); didFinishLoading(0, monotonicallyIncreasingTime(), encodedDataLength); }
void DocumentThreadableLoader::didFinishLoading(SubresourceLoader* loader) { ASSERT(loader == m_loader); ASSERT(m_client); didFinishLoading(loader->identifier()); }
void WebCoreSynchronousLoader::didFail(ResourceHandle* handle, const ResourceError& error) { m_error = error; didFinishLoading(handle); }
void ResourceLoader::didFinishLoading(ResourceHandle*, double finishTime) { didFinishLoading(finishTime); }
void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, SecurityCheckPolicy securityCheck) { // Any credential should have been removed from the cross-site requests. const URL& requestURL = request.url(); m_options.setSecurityCheck(securityCheck); ASSERT(m_sameOriginRequest || requestURL.user().isEmpty()); ASSERT(m_sameOriginRequest || requestURL.pass().isEmpty()); if (m_async) { ThreadableLoaderOptions options = m_options; options.setClientCredentialPolicy(DoNotAskClientForCrossOriginCredentials); if (m_actualRequest) { // Don't sniff content or send load callbacks for the preflight request. options.setSendLoadCallbacks(DoNotSendCallbacks); options.setSniffContent(DoNotSniffContent); // Keep buffering the data for the preflight request. options.setDataBufferingPolicy(BufferData); } CachedResourceRequest newRequest(request, options); if (RuntimeEnabledFeatures::sharedFeatures().resourceTimingEnabled()) newRequest.setInitiator(m_options.initiator); ASSERT(!m_resource); m_resource = m_document.cachedResourceLoader().requestRawResource(newRequest); if (m_resource) m_resource->addClient(this); return; } // FIXME: ThreadableLoaderOptions.sniffContent is not supported for synchronous requests. RefPtr<SharedBuffer> data; ResourceError error; ResourceResponse response; unsigned long identifier = std::numeric_limits<unsigned long>::max(); if (m_document.frame()) identifier = m_document.frame()->loader().loadResourceSynchronously(request, m_options.allowCredentials(), m_options.clientCredentialPolicy(), error, response, data); if (!error.isNull() && response.httpStatusCode() <= 0) { if (requestURL.isLocalFile()) { // We don't want XMLHttpRequest to raise an exception for file:// resources, see <rdar://problem/4962298>. // FIXME: XMLHttpRequest quirks should be in XMLHttpRequest code, not in DocumentThreadableLoader.cpp. didReceiveResponse(identifier, response); didFinishLoading(identifier, 0.0); return; } m_client->didFail(error); return; } // FIXME: FrameLoader::loadSynchronously() does not tell us whether a redirect happened or not, so we guess by comparing the // request and response URLs. This isn't a perfect test though, since a server can serve a redirect to the same URL that was // requested. Also comparing the request and response URLs as strings will fail if the requestURL still has its credentials. bool didRedirect = requestURL != response.url(); if (didRedirect && (!isAllowedByContentSecurityPolicy(response.url(), didRedirect) || !isAllowedRedirect(response.url()))) { m_client->didFailRedirectCheck(); return; } didReceiveResponse(identifier, response); if (data) didReceiveData(identifier, data->data(), data->size()); didFinishLoading(identifier, 0.0); }
void DocumentThreadableLoader::loadRequest(const ResourceRequest& request) { // Any credential should have been removed from the cross-site requests. const KURL& requestURL = request.url(); ASSERT(m_sameOriginRequest || requestURL.user().isEmpty()); ASSERT(m_sameOriginRequest || requestURL.pass().isEmpty()); ThreadableLoaderOptions options = m_options; if (m_async) { if (m_actualRequest) { options.sniffContent = DoNotSniffContent; options.dataBufferingPolicy = BufferData; } if (m_options.timeoutMilliseconds > 0) m_timeoutTimer.startOneShot(m_options.timeoutMilliseconds / 1000.0); FetchRequest newRequest(request, m_options.initiator, options); ASSERT(!resource()); setResource(m_document->fetcher()->fetchRawResource(newRequest)); if (resource() && resource()->loader()) { unsigned long identifier = resource()->identifier(); InspectorInstrumentation::documentThreadableLoaderStartedLoadingForClient(m_document, identifier, m_client); } return; } FetchRequest fetchRequest(request, m_options.initiator, options); ResourcePtr<Resource> resource = m_document->fetcher()->fetchSynchronously(fetchRequest); ResourceResponse response = resource ? resource->response() : ResourceResponse(); unsigned long identifier = resource ? resource->identifier() : std::numeric_limits<unsigned long>::max(); ResourceError error = resource ? resource->resourceError() : ResourceError(); InspectorInstrumentation::documentThreadableLoaderStartedLoadingForClient(m_document, identifier, m_client); if (!resource) { m_client->didFail(error); return; } // No exception for file:/// resources, see <rdar://problem/4962298>. // Also, if we have an HTTP response, then it wasn't a network error in fact. if (!error.isNull() && !requestURL.isLocalFile() && response.httpStatusCode() <= 0) { m_client->didFail(error); return; } // FIXME: A synchronous request does not tell us whether a redirect happened or not, so we guess by comparing the // request and response URLs. This isn't a perfect test though, since a server can serve a redirect to the same URL that was // requested. Also comparing the request and response URLs as strings will fail if the requestURL still has its credentials. if (requestURL != response.url() && (!isAllowedByPolicy(response.url()) || !isAllowedRedirect(response.url()))) { m_client->didFailRedirectCheck(); return; } didReceiveResponse(identifier, response); SharedBuffer* data = resource->resourceBuffer(); if (data) didReceiveData(data->data(), data->size()); didFinishLoading(identifier, 0.0); }
void MainResourceLoader::continueAfterContentPolicy(PolicyAction contentPolicy, const ResourceResponse& r) { KURL url = request().url(); const String& mimeType = r.mimeType(); switch (contentPolicy) { case PolicyUse: { // Prevent remote web archives from loading because they can claim to be from any domain and thus avoid cross-domain security checks (4120255). bool isRemoteWebArchive = (equalIgnoringCase("application/x-webarchive", mimeType) || equalIgnoringCase("multipart/related", mimeType)) && !m_substituteData.isValid() && !url.isLocalFile(); if (!frameLoader()->client()->canShowMIMEType(mimeType) || isRemoteWebArchive) { frameLoader()->policyChecker()->cannotShowMIMEType(r); // Check reachedTerminalState since the load may have already been cancelled inside of _handleUnimplementablePolicyWithErrorCode::. if (!reachedTerminalState()) stopLoadingForPolicyChange(); return; } break; } case PolicyDownload: // m_handle can be null, e.g. when loading a substitute resource from application cache. if (!m_handle) { receivedError(cannotShowURLError()); return; } frameLoader()->client()->download(m_handle.get(), request(), m_handle.get()->firstRequest(), r); // It might have gone missing if (frameLoader()) receivedError(interruptedForPolicyChangeError()); return; case PolicyIgnore: stopLoadingForPolicyChange(); return; default: ASSERT_NOT_REACHED(); } RefPtr<MainResourceLoader> protect(this); if (r.isHTTP()) { int status = r.httpStatusCode(); if (status < 200 || status >= 300) { bool hostedByObject = frameLoader()->isHostedByObjectElement(); frameLoader()->handleFallbackContent(); // object elements are no longer rendered after we fallback, so don't // keep trying to process data from their load if (hostedByObject) cancel(); } } // we may have cancelled this load as part of switching to fallback content if (!reachedTerminalState()) ResourceLoader::didReceiveResponse(r); if (frameLoader() && !frameLoader()->isStopping()) { if (m_substituteData.isValid()) { if (m_substituteData.content()->size()) didReceiveData(m_substituteData.content()->data(), m_substituteData.content()->size(), m_substituteData.content()->size(), true); if (frameLoader() && !frameLoader()->isStopping()) didFinishLoading(0); } else if (shouldLoadAsEmptyDocument(url) || frameLoader()->client()->representationExistsForURLScheme(url.protocol())) didFinishLoading(0); } }
void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, SecurityCheckPolicy securityCheck) { // Any credential should have been removed from the cross-site requests. const KURL& requestURL = request.url(); m_options.securityCheck = securityCheck; ASSERT(m_sameOriginRequest || requestURL.user().isEmpty()); ASSERT(m_sameOriginRequest || requestURL.pass().isEmpty()); if (m_async) { ThreadableLoaderOptions options = m_options; options.crossOriginCredentialPolicy = DoNotAskClientForCrossOriginCredentials; if (m_actualRequest) { // Don't sniff content or send load callbacks for the preflight request. options.sendLoadCallbacks = DoNotSendCallbacks; options.sniffContent = DoNotSniffContent; // Keep buffering the data for the preflight request. options.shouldBufferData = BufferData; } CachedResourceRequest newRequest(request, options); #if ENABLE(INSPECTOR) if (m_actualRequest) { // Because willSendRequest only gets called during redirects, we initialize the identifier and the first willSendRequest here. m_preflightRequestIdentifier = m_document->frame()->page()->progress()->createUniqueIdentifier(); ResourceResponse redirectResponse = ResourceResponse(); InspectorInstrumentation::willSendRequest(m_document->frame(), m_preflightRequestIdentifier, m_document->frame()->loader()->documentLoader(), newRequest.mutableResourceRequest(), redirectResponse); } #endif ASSERT(!m_resource); m_resource = m_document->cachedResourceLoader()->requestRawResource(newRequest); if (m_resource) { #if ENABLE(INSPECTOR) if (m_resource->loader()) { unsigned long identifier = m_actualRequest ? m_preflightRequestIdentifier : m_resource->loader()->identifier(); InspectorInstrumentation::documentThreadableLoaderStartedLoadingForClient(m_document, identifier, m_client); } #endif m_resource->addClient(this); } return; } // FIXME: ThreadableLoaderOptions.sniffContent is not supported for synchronous requests. Vector<char> data; ResourceError error; ResourceResponse response; unsigned long identifier = std::numeric_limits<unsigned long>::max(); if (m_document->frame()) identifier = m_document->frame()->loader()->loadResourceSynchronously(request, m_options.allowCredentials, error, response, data); InspectorInstrumentation::documentThreadableLoaderStartedLoadingForClient(m_document, identifier, m_client); // No exception for file:/// resources, see <rdar://problem/4962298>. // Also, if we have an HTTP response, then it wasn't a network error in fact. if (!error.isNull() && !requestURL.isLocalFile() && response.httpStatusCode() <= 0) { m_client->didFail(error); return; } // FIXME: FrameLoader::loadSynchronously() does not tell us whether a redirect happened or not, so we guess by comparing the // request and response URLs. This isn't a perfect test though, since a server can serve a redirect to the same URL that was // requested. Also comparing the request and response URLs as strings will fail if the requestURL still has its credentials. if (requestURL != response.url() && !isAllowedRedirect(response.url())) { m_client->didFailRedirectCheck(); return; } didReceiveResponse(identifier, response); const char* bytes = static_cast<const char*>(data.data()); int len = static_cast<int>(data.size()); dataReceived(0, bytes, len); didFinishLoading(identifier, 0.0); }
void SubresourceLoader::willSendRequestInternal(ResourceRequest& newRequest, const ResourceResponse& redirectResponse) { // Store the previous URL because the call to ResourceLoader::willSendRequest will modify it. URL previousURL = request().url(); Ref<SubresourceLoader> protectedThis(*this); if (!newRequest.url().isValid()) { cancel(cannotShowURLError()); return; } ASSERT(!newRequest.isNull()); if (!redirectResponse.isNull()) { if (options().redirect != FetchOptions::Redirect::Follow) { if (options().redirect == FetchOptions::Redirect::Error) { cancel(); return; } ResourceResponse opaqueRedirectedResponse; opaqueRedirectedResponse.setType(ResourceResponse::Type::Opaqueredirect); m_resource->responseReceived(opaqueRedirectedResponse); didFinishLoading(currentTime()); return; } // CachedResources are keyed off their original request URL. // Requesting the same original URL a second time can redirect to a unique second resource. // Therefore, if a redirect to a different destination URL occurs, we should no longer consider this a revalidation of the first resource. // Doing so would have us reusing the resource from the first request if the second request's revalidation succeeds. if (newRequest.isConditional() && m_resource->resourceToRevalidate() && newRequest.url() != m_resource->resourceToRevalidate()->response().url()) { newRequest.makeUnconditional(); MemoryCache::singleton().revalidationFailed(*m_resource); if (m_frame && m_frame->page()) m_frame->page()->diagnosticLoggingClient().logDiagnosticMessageWithResult(DiagnosticLoggingKeys::cachedResourceRevalidationKey(), emptyString(), DiagnosticLoggingResultFail, ShouldSample::Yes); } if (!m_documentLoader->cachedResourceLoader().canRequest(m_resource->type(), newRequest.url(), options(), false /* forPreload */, true /* didReceiveRedirectResponse */)) { cancel(); return; } if (!checkRedirectionCrossOriginAccessControl(request(), redirectResponse, newRequest)) { cancel(); return; } if (m_resource->isImage() && m_documentLoader->cachedResourceLoader().shouldDeferImageLoad(newRequest.url())) { cancel(); return; } m_resource->redirectReceived(newRequest, redirectResponse); } if (newRequest.isNull() || reachedTerminalState()) return; ResourceLoader::willSendRequestInternal(newRequest, redirectResponse); if (newRequest.isNull()) cancel(); ResourceLoadObserver::sharedObserver().logSubresourceLoading(m_frame.get(), newRequest, redirectResponse); }
void ResourceLoader::didFinishLoading(ResourceHandle*) { didFinishLoading(); }
void MainResourceLoader::continueAfterContentPolicy(PolicyAction contentPolicy, const ResourceResponse& r) { KURL url = request().url(); const String& mimeType = r.mimeType(); switch (contentPolicy) { case PolicyUse: { // Prevent remote web archives from loading because they can claim to be from any domain and thus avoid cross-domain security checks (4120255). bool isRemoteWebArchive = (equalIgnoringCase("application/x-webarchive", mimeType) #if PLATFORM(GTK) || equalIgnoringCase("message/rfc822", mimeType) #endif || equalIgnoringCase("multipart/related", mimeType)) && !m_substituteData.isValid() && !SchemeRegistry::shouldTreatURLSchemeAsLocal(url.protocol()); if (!frameLoader()->client()->canShowMIMEType(mimeType) || isRemoteWebArchive) { frameLoader()->policyChecker()->cannotShowMIMEType(r); // Check reachedTerminalState since the load may have already been canceled inside of _handleUnimplementablePolicyWithErrorCode::. if (!reachedTerminalState()) stopLoadingForPolicyChange(); return; } break; } case PolicyDownload: { // m_handle can be null, e.g. when loading a substitute resource from application cache. if (!m_handle) { receivedError(cannotShowURLError()); return; } InspectorInstrumentation::continueWithPolicyDownload(m_frame.get(), documentLoader(), identifier(), r); // When starting the request, we didn't know that it would result in download and not navigation. Now we know that main document URL didn't change. // Download may use this knowledge for purposes unrelated to cookies, notably for setting file quarantine data. ResourceRequest request = this->request(); frameLoader()->setOriginalURLForDownloadRequest(request); frameLoader()->client()->download(m_handle.get(), request, r); // It might have gone missing if (frameLoader()) receivedError(interruptedForPolicyChangeError()); return; } case PolicyIgnore: InspectorInstrumentation::continueWithPolicyIgnore(m_frame.get(), documentLoader(), identifier(), r); stopLoadingForPolicyChange(); return; default: ASSERT_NOT_REACHED(); } RefPtr<MainResourceLoader> protect(this); if (r.isHTTP()) { int status = r.httpStatusCode(); if (status < 200 || status >= 300) { bool hostedByObject = frameLoader()->isHostedByObjectElement(); frameLoader()->handleFallbackContent(); // object elements are no longer rendered after we fallback, so don't // keep trying to process data from their load if (hostedByObject) cancel(); } } // we may have cancelled this load as part of switching to fallback content if (!reachedTerminalState()) ResourceLoader::didReceiveResponse(r); if (frameLoader() && !frameLoader()->activeDocumentLoader()->isStopping()) { if (m_substituteData.isValid()) { if (m_substituteData.content()->size()) didReceiveData(m_substituteData.content()->data(), m_substituteData.content()->size(), m_substituteData.content()->size(), true); if (frameLoader() && !frameLoader()->activeDocumentLoader()->isStopping()) didFinishLoading(0); } else if (shouldLoadAsEmptyDocument(url) || frameLoader()->client()->representationExistsForURLScheme(url.protocol())) didFinishLoading(0); } }
void SubresourceLoader::willSendRequestInternal(ResourceRequest& newRequest, const ResourceResponse& redirectResponse) { // Store the previous URL because the call to ResourceLoader::willSendRequest will modify it. URL previousURL = request().url(); Ref<SubresourceLoader> protectedThis(*this); if (!newRequest.url().isValid()) { cancel(cannotShowURLError()); return; } if (newRequest.requester() != ResourceRequestBase::Requester::Main) ResourceLoadObserver::sharedObserver().logSubresourceLoading(m_frame.get(), newRequest, redirectResponse); ASSERT(!newRequest.isNull()); if (!redirectResponse.isNull()) { if (options().redirect != FetchOptions::Redirect::Follow) { if (options().redirect == FetchOptions::Redirect::Error) { cancel(); return; } ResourceResponse opaqueRedirectedResponse; opaqueRedirectedResponse.setURL(redirectResponse.url()); opaqueRedirectedResponse.setType(ResourceResponse::Type::Opaqueredirect); m_resource->responseReceived(opaqueRedirectedResponse); didFinishLoading(currentTime()); return; } else if (m_redirectCount++ >= options().maxRedirectCount) { cancel(ResourceError(String(), 0, request().url(), ASCIILiteral("Too many redirections"), ResourceError::Type::General)); return; } // CachedResources are keyed off their original request URL. // Requesting the same original URL a second time can redirect to a unique second resource. // Therefore, if a redirect to a different destination URL occurs, we should no longer consider this a revalidation of the first resource. // Doing so would have us reusing the resource from the first request if the second request's revalidation succeeds. if (newRequest.isConditional() && m_resource->resourceToRevalidate() && newRequest.url() != m_resource->resourceToRevalidate()->response().url()) { newRequest.makeUnconditional(); MemoryCache::singleton().revalidationFailed(*m_resource); if (m_frame && m_frame->page()) m_frame->page()->diagnosticLoggingClient().logDiagnosticMessageWithResult(DiagnosticLoggingKeys::cachedResourceRevalidationKey(), emptyString(), DiagnosticLoggingResultFail, ShouldSample::Yes); } if (!m_documentLoader->cachedResourceLoader().updateRequestAfterRedirection(m_resource->type(), newRequest, options())) { cancel(); return; } String errorDescription; if (!checkRedirectionCrossOriginAccessControl(request(), redirectResponse, newRequest, errorDescription)) { String errorMessage = "Cross-origin redirection to " + newRequest.url().string() + " denied by Cross-Origin Resource Sharing policy: " + errorDescription; if (m_frame && m_frame->document()) m_frame->document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, errorMessage); cancel(ResourceError(String(), 0, request().url(), errorMessage, ResourceError::Type::AccessControl)); return; } if (m_resource->isImage() && m_documentLoader->cachedResourceLoader().shouldDeferImageLoad(newRequest.url())) { cancel(); return; } m_loadTiming.addRedirect(redirectResponse.url(), newRequest.url()); m_resource->redirectReceived(newRequest, redirectResponse); } if (newRequest.isNull() || reachedTerminalState()) return; ResourceLoader::willSendRequestInternal(newRequest, redirectResponse); if (newRequest.isNull()) { cancel(); return; } if (m_resource->type() == CachedResource::MainResource && !redirectResponse.isNull()) m_documentLoader->willContinueMainResourceLoadAfterRedirect(newRequest); }