void Loader::Host::servePendingRequests(RequestQueue& requestsPending, bool& serveLowerPriority) { while (!requestsPending.isEmpty()) { Request* request = requestsPending.first(); DocLoader* docLoader = request->docLoader(); bool resourceIsCacheValidator = request->cachedResource()->isCacheValidator(); // For named hosts - which are only http(s) hosts - we should always enforce the connection limit. // For non-named hosts - everything but http(s) - we should only enforce the limit if the document isn't done parsing // and we don't know all stylesheets yet. bool shouldLimitRequests = !m_name.isNull() || docLoader->doc()->parsing() || !docLoader->doc()->haveStylesheetsLoaded(); if (shouldLimitRequests && m_requestsLoading.size() + m_nonCachedRequestsInFlight >= m_maxRequestsInFlight) { serveLowerPriority = false; cache()->loader()->scheduleServePendingRequests(); return; } requestsPending.removeFirst(); ResourceRequest resourceRequest(request->cachedResource()->url()); resourceRequest.setTargetType(cachedResourceTypeToTargetType(request->cachedResource()->type())); if (!request->cachedResource()->accept().isEmpty()) resourceRequest.setHTTPAccept(request->cachedResource()->accept()); // Do not set the referrer or HTTP origin here. That's handled by SubresourceLoader::create. if (resourceIsCacheValidator) { CachedResource* resourceToRevalidate = request->cachedResource()->resourceToRevalidate(); ASSERT(resourceToRevalidate->canUseCacheValidator()); ASSERT(resourceToRevalidate->isLoaded()); const String& lastModified = resourceToRevalidate->response().httpHeaderField("Last-Modified"); const String& eTag = resourceToRevalidate->response().httpHeaderField("ETag"); if (!lastModified.isEmpty() || !eTag.isEmpty()) { ASSERT(docLoader->cachePolicy() != CachePolicyReload); if (docLoader->cachePolicy() == CachePolicyRevalidate) resourceRequest.setHTTPHeaderField("Cache-Control", "max-age=0"); if (!lastModified.isEmpty()) resourceRequest.setHTTPHeaderField("If-Modified-Since", lastModified); if (!eTag.isEmpty()) resourceRequest.setHTTPHeaderField("If-None-Match", eTag); } } RefPtr<SubresourceLoader> loader = SubresourceLoader::create(docLoader->doc()->frame(), this, resourceRequest, request->shouldDoSecurityCheck(), request->sendResourceLoadCallbacks()); if (loader) { m_requestsLoading.add(loader.release(), request); request->cachedResource()->setRequestedFromNetworkingLayer(); #if REQUEST_DEBUG printf("HOST %s COUNT %d LOADING %s\n", resourceRequest.url().host().latin1().data(), m_requestsLoading.size(), request->cachedResource()->url().latin1().data()); #endif } else { docLoader->decrementRequestCount(); docLoader->setLoadInProgress(true); request->cachedResource()->error(); docLoader->setLoadInProgress(false); delete request; } } }
void CachedResource::load(CachedResourceLoader* cachedResourceLoader, const ResourceLoaderOptions& options) { if (!cachedResourceLoader->frame()) { failBeforeStarting(); return; } m_options = options; m_loading = true; if (!accept().isEmpty()) m_resourceRequest.setHTTPAccept(accept()); if (isCacheValidator()) { CachedResource* resourceToRevalidate = m_resourceToRevalidate; ASSERT(resourceToRevalidate->canUseCacheValidator()); ASSERT(resourceToRevalidate->isLoaded()); const String& lastModified = resourceToRevalidate->response().httpHeaderField("Last-Modified"); const String& eTag = resourceToRevalidate->response().httpHeaderField("ETag"); if (!lastModified.isEmpty() || !eTag.isEmpty()) { ASSERT(cachedResourceLoader->cachePolicy(type()) != CachePolicyReload); if (cachedResourceLoader->cachePolicy(type()) == CachePolicyRevalidate) m_resourceRequest.setHTTPHeaderField("Cache-Control", "max-age=0"); if (!lastModified.isEmpty()) m_resourceRequest.setHTTPHeaderField("If-Modified-Since", lastModified); if (!eTag.isEmpty()) m_resourceRequest.setHTTPHeaderField("If-None-Match", eTag); } } if (type() == CachedResource::LinkPrefetch || type() == CachedResource::LinkSubresource) m_resourceRequest.setHTTPHeaderField("Purpose", "prefetch"); m_resourceRequest.setPriority(loadPriority()); // FIXME: It's unfortunate that the cache layer and below get to know anything about fragment identifiers. // We should look into removing the expectation of that knowledge from the platform network stacks. ResourceRequest request(m_resourceRequest); if (!m_fragmentIdentifierForRequest.isNull()) { KURL url = request.url(); url.setFragmentIdentifier(m_fragmentIdentifierForRequest); request.setURL(url); m_fragmentIdentifierForRequest = String(); } m_loader = ResourceLoader::create(cachedResourceLoader->frame(), this, request, options); if (!m_loader) { failBeforeStarting(); return; } m_status = Pending; }
PassOwnPtr<CachedResourceRequest> CachedResourceRequest::load(CachedResourceLoader* cachedResourceLoader, CachedResource* resource, bool incremental, SecurityCheckPolicy securityCheck, const ResourceLoaderOptions& options) { OwnPtr<CachedResourceRequest> request = adoptPtr(new CachedResourceRequest(cachedResourceLoader, resource, incremental)); ResourceRequest resourceRequest = resource->resourceRequest(); #if PLATFORM(CHROMIUM) resourceRequest.setTargetType(cachedResourceTypeToTargetType(resource->type())); #endif if (!resource->accept().isEmpty()) resourceRequest.setHTTPAccept(resource->accept()); if (resource->isCacheValidator()) { CachedResource* resourceToRevalidate = resource->resourceToRevalidate(); ASSERT(resourceToRevalidate->canUseCacheValidator()); ASSERT(resourceToRevalidate->isLoaded()); const String& lastModified = resourceToRevalidate->response().httpHeaderField("Last-Modified"); const String& eTag = resourceToRevalidate->response().httpHeaderField("ETag"); if (!lastModified.isEmpty() || !eTag.isEmpty()) { ASSERT(cachedResourceLoader->cachePolicy() != CachePolicyReload); if (cachedResourceLoader->cachePolicy() == CachePolicyRevalidate) resourceRequest.setHTTPHeaderField("Cache-Control", "max-age=0"); if (!lastModified.isEmpty()) resourceRequest.setHTTPHeaderField("If-Modified-Since", lastModified); if (!eTag.isEmpty()) resourceRequest.setHTTPHeaderField("If-None-Match", eTag); } } #if ENABLE(LINK_PREFETCH) if (resource->type() == CachedResource::LinkPrefetch || resource->type() == CachedResource::LinkPrerender || resource->type() == CachedResource::LinkSubresource) resourceRequest.setHTTPHeaderField("Purpose", "prefetch"); #endif ResourceLoadPriority priority = resource->loadPriority(); resourceRequest.setPriority(priority); RefPtr<SubresourceLoader> loader = resourceLoadScheduler()->scheduleSubresourceLoad(cachedResourceLoader->document()->frame(), request.get(), resourceRequest, priority, securityCheck, options); if (!loader || loader->reachedTerminalState()) { // FIXME: What if resources in other frames were waiting for this revalidation? LOG(ResourceLoading, "Cannot start loading '%s'", resource->url().string().latin1().data()); if (resource->resourceToRevalidate()) memoryCache()->revalidationFailed(resource); resource->error(CachedResource::LoadError); //+EAWebKitChange //10/19/2012 return PassOwnPtr<CachedResourceRequest>(std::nullptr_t()) ; //-EAWebKitChange } request->m_loader = loader; return request.release(); }
void InspectorResource::updateResponse(const ResourceResponse& response) { m_expectedContentLength = response.expectedContentLength(); m_mimeType = response.mimeType(); if (m_mimeType.isEmpty() && response.httpStatusCode() == 304) { CachedResource* cachedResource = cache()->resourceForURL(response.url().string()); if (cachedResource) m_mimeType = cachedResource->response().mimeType(); } m_responseHeaderFields = response.httpHeaderFields(); m_responseStatusCode = response.httpStatusCode(); m_responseStatusText = response.httpStatusText(); m_suggestedFilename = response.suggestedFilename(); m_connectionID = response.connectionID(); m_connectionReused = response.connectionReused(); m_loadTiming = response.resourceLoadTiming(); m_cached = response.wasCached(); if (!m_cached && m_loadTiming && m_loadTiming->requestTime) m_responseReceivedTime = m_loadTiming->requestTime + m_loadTiming->receiveHeadersEnd / 1000.0; else m_responseReceivedTime = currentTime(); m_changes.set(TimingChange); m_changes.set(ResponseChange); m_changes.set(TypeChange); }
void InspectorResourceAgent::didReceiveResponse(unsigned long identifier, DocumentLoader* loader, const ResourceResponse& response) { RefPtr<InspectorObject> resourceResponse = buildObjectForResourceResponse(response); String type = "Other"; long cachedResourceSize = 0; if (loader) { CachedResource* cachedResource = InspectorResourceAgent::cachedResource(loader->frame(), response.url()); if (cachedResource) { type = cachedResourceTypeString(*cachedResource); cachedResourceSize = cachedResource->encodedSize(); // Use mime type from cached resource in case the one in response is empty. if (response.mimeType().isEmpty()) resourceResponse->setString("mimeType", cachedResource->response().mimeType()); } if (equalIgnoringFragmentIdentifier(response.url(), loader->frameLoader()->iconURL())) type = "Image"; else if (equalIgnoringFragmentIdentifier(response.url(), loader->url()) && type == "Other") type = "Document"; } m_frontend->didReceiveResponse(identifier, currentTime(), type, resourceResponse); // If we revalidated the resource and got Not modified, send content length following didReceiveResponse // as there will be no calls to didReceiveContentLength from the network stack. if (cachedResourceSize && response.httpStatusCode() == 304) didReceiveContentLength(identifier, cachedResourceSize); }
void Loader::Host::didReceiveData(SubresourceLoader* loader, const char* data, int size) { Request* request = m_requestsLoading.get(loader); if (!request) return; CachedResource* resource = request->cachedResource(); ASSERT(!resource->isCacheValidator()); if (resource->errorOccurred()) return; m_processingResource = true; if (resource->response().httpStatusCode() / 100 == 4) { // Treat a 4xx response like a network error. resource->error(); m_processingResource = false; return; } // Set the data. if (request->isMultipart()) { // The loader delivers the data in a multipart section all at once, send eof. // The resource data will change as the next part is loaded, so we need to make a copy. RefPtr<SharedBuffer> copiedData = SharedBuffer::create(data, size); resource->data(copiedData.release(), true); } else if (request->isIncremental()) resource->data(loader->resourceData(), false); m_processingResource = false; }
HRESULT STDMETHODCALLTYPE WebDataSource::subresourceForURL( /* [in] */ BSTR url, /* [retval][out] */ IWebResource** resource) { if (!resource) { ASSERT_NOT_REACHED(); return E_POINTER; } *resource = 0; Document *doc = m_loader->frameLoader()->frame().document(); if (!doc) return E_FAIL; CachedResource *cachedResource = doc->cachedResourceLoader()->cachedResource(String(url)); if (!cachedResource) return E_FAIL; ResourceBuffer* buffer = cachedResource->resourceBuffer(); *resource = WebResource::createInstance(buffer ? buffer->sharedBuffer() : 0, cachedResource->response()); return S_OK; }
PassRefPtr<InspectorObject> InspectorPageAgent::buildObjectForFrameTree(Frame* frame) { RefPtr<InspectorObject> result = InspectorObject::create(); RefPtr<InspectorObject> frameObject = buildObjectForFrame(frame); result->setObject("frame", frameObject); RefPtr<InspectorArray> subresources = InspectorArray::create(); result->setArray("resources", subresources); Vector<CachedResource*> allResources = cachedResourcesForFrame(frame); for (Vector<CachedResource*>::const_iterator it = allResources.begin(); it != allResources.end(); ++it) { CachedResource* cachedResource = *it; RefPtr<InspectorObject> resourceObject = InspectorObject::create(); resourceObject->setString("url", cachedResource->url()); resourceObject->setString("type", cachedResourceTypeString(*cachedResource)); resourceObject->setString("mimeType", cachedResource->response().mimeType()); subresources->pushValue(resourceObject); } RefPtr<InspectorArray> childrenArray; for (Frame* child = frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) { if (!childrenArray) { childrenArray = InspectorArray::create(); result->setArray("childFrames", childrenArray); } childrenArray->pushObject(buildObjectForFrameTree(child)); } return result; }
void Loader::Host::didReceiveData(SubresourceLoader* loader, const char* data, int size) { RefPtr<Host> protector(this); Request* request = m_requestsLoading.get(loader); if (!request) return; CachedResource* resource = request->cachedResource(); ASSERT(!resource->isCacheValidator()); if (resource->errorOccurred()) return; if (resource->response().httpStatusCode() / 100 == 4) { // Treat a 4xx response like a network error for all resources but images (which will ignore the error and continue to load for // legacy compatibility). resource->httpStatusCodeError(); return; } // Set the data. if (request->isMultipart()) { // The loader delivers the data in a multipart section all at once, send eof. // The resource data will change as the next part is loaded, so we need to make a copy. RefPtr<SharedBuffer> copiedData = SharedBuffer::create(data, size); resource->data(copiedData.release(), true); } else if (request->isIncremental()) resource->data(loader->resourceData(), false); }
static PassRefPtr<InspectorObject> buildObjectForCachedResource(DocumentLoader* loader, const CachedResource& cachedResource) { RefPtr<InspectorObject> resourceObject = InspectorObject::create(); resourceObject->setString("url", cachedResource.url()); resourceObject->setString("type", cachedResourceTypeString(cachedResource)); resourceObject->setNumber("encodedSize", cachedResource.encodedSize()); resourceObject->setObject("response", buildObjectForResourceResponse(cachedResource.response())); resourceObject->setObject("loader", buildObjectForDocumentLoader(loader)); return resourceObject; }
static PassRefPtr<InspectorObject> buildObjectForCachedResource(const CachedResource& cachedResource, DocumentLoader* loader) { RefPtr<InspectorObject> resourceObject = InspectorObject::create(); resourceObject->setString("url", cachedResource.url()); resourceObject->setString("type", InspectorPageAgent::cachedResourceTypeString(cachedResource)); resourceObject->setNumber("bodySize", cachedResource.encodedSize()); RefPtr<InspectorObject> resourceResponse = buildObjectForResourceResponse(cachedResource.response(), loader); if (resourceResponse) resourceObject->setObject("response", resourceResponse); return resourceObject; }
String PageDebuggerAgent::sourceMapURLForScript(const Script& script) { DEFINE_STATIC_LOCAL(String, sourceMapHTTPHeader, (ASCIILiteral("SourceMap"))); DEFINE_STATIC_LOCAL(String, sourceMapHTTPHeaderDeprecated, (ASCIILiteral("X-SourceMap"))); if (!script.url.isEmpty()) { CachedResource* resource = m_pageAgent->cachedResource(m_pageAgent->mainFrame(), URL(ParsedURLString, script.url)); if (resource) { String sourceMapHeader = resource->response().httpHeaderField(sourceMapHTTPHeader); if (!sourceMapHeader.isEmpty()) return sourceMapHeader; sourceMapHeader = resource->response().httpHeaderField(sourceMapHTTPHeaderDeprecated); if (!sourceMapHeader.isEmpty()) return sourceMapHeader; } } return InspectorDebuggerAgent::sourceMapURLForScript(script); }
String InspectorDebuggerAgent::sourceMapURLForScript(const Script& script) { DEFINE_STATIC_LOCAL(String, sourceMapHTTPHeader, (ASCIILiteral("SourceMap"))); DEFINE_STATIC_LOCAL(String, sourceMapHTTPHeaderDeprecated, (ASCIILiteral("X-SourceMap"))); if (!script.url.isEmpty()) { if (InspectorPageAgent* pageAgent = m_instrumentingAgents->inspectorPageAgent()) { CachedResource* resource = pageAgent->cachedResource(pageAgent->mainFrame(), URL(ParsedURLString, script.url)); if (resource) { String sourceMapHeader = resource->response().httpHeaderField(sourceMapHTTPHeader); if (!sourceMapHeader.isEmpty()) return sourceMapHeader; sourceMapHeader = resource->response().httpHeaderField(sourceMapHTTPHeaderDeprecated); if (!sourceMapHeader.isEmpty()) return sourceMapHeader; } } } return ContentSearchUtils::findScriptSourceMapURL(script.source); }
WebResource* WebDataSource::subresourceForURL(String url) { Document *doc = m_loader->frameLoader()->frame()->document(); if (!doc) return 0; CachedResource *cachedResource = doc->docLoader()->cachedResource(String(url)); if (!cachedResource) return 0; return WebResource::createInstance(cachedResource->data(), cachedResource->response()); }
PassRefPtr<ArchiveResource> DocumentLoader::subresource(const KURL& url) const { if (!isCommitted()) return 0; Document* doc = m_frame->document(); if (!doc) return archiveResourceForURL(url); CachedResource* resource = doc->docLoader()->cachedResource(url); if (!resource || resource->preloadResult() == CachedResource::PreloadReferenced) return archiveResourceForURL(url); return ArchiveResource::create(resource->data(), url, resource->response()); }
void InspectorResource::updateResponse(const ResourceResponse& response) { m_expectedContentLength = response.expectedContentLength(); m_mimeType = response.mimeType(); if (m_mimeType.isEmpty() && response.httpStatusCode() == 304) { CachedResource* cachedResource = cache()->resourceForURL(response.url().string()); if (cachedResource) m_mimeType = cachedResource->response().mimeType(); } m_responseHeaderFields = response.httpHeaderFields(); m_responseStatusCode = response.httpStatusCode(); m_suggestedFilename = response.suggestedFilename(); m_changes.set(ResponseChange); m_changes.set(TypeChange); }
void CachedResource::loadFrom(const CachedResource& resource) { ASSERT(url() == resource.url()); ASSERT(type() == resource.type()); ASSERT(resource.status() == Status::Cached); if (isCrossOrigin() && m_options.mode == FetchOptions::Mode::Cors) { ASSERT(m_origin); String errorMessage; if (!WebCore::passesAccessControlCheck(resource.response(), m_options.allowCredentials, *m_origin, errorMessage)) { setResourceError(ResourceError(String(), 0, url(), errorMessage, ResourceError::Type::AccessControl)); return; } } setBodyDataFrom(resource); setStatus(Status::Cached); setLoading(false); }
PassRefPtr<ArchiveResource> DocumentLoader::subresource(const KURL& url) const { if (!isCommitted()) return 0; CachedResource* resource = m_frame->document()->docLoader()->cachedResource(url); if (!resource || !resource->isLoaded()) return archiveResourceForURL(url); // FIXME: This has the side effect of making the resource non-purgeable. // It would be better if it didn't have this permanent effect. if (!resource->makePurgeable(false)) return 0; RefPtr<SharedBuffer> data = resource->data(); if (!data) return 0; return ArchiveResource::create(data.release(), url, resource->response()); }
String InspectorDebuggerAgent::sourceMapURLForScript(const Script& script) { DEFINE_STATIC_LOCAL(String, sourceMapHttpHeader, ("X-SourceMap")); String sourceMapURL = ContentSearchUtils::findSourceMapURL(script.source); if (!sourceMapURL.isEmpty()) return sourceMapURL; if (script.url.isEmpty()) return String(); InspectorPageAgent* pageAgent = m_instrumentingAgents->inspectorPageAgent(); if (!pageAgent) return String(); CachedResource* resource = pageAgent->cachedResource(pageAgent->mainFrame(), KURL(ParsedURLString, script.url)); if (resource) return resource->response().httpHeaderField(sourceMapHttpHeader); return String(); }
void InspectorResourceAgent::didReceiveResourceResponse(unsigned long identifier, DocumentLoader* loader, const ResourceResponse& response, ResourceLoader* resourceLoader) { if (!loader) return; String requestId = IdentifiersFactory::requestId(identifier); RefPtr<TypeBuilder::Network::Response> resourceResponse = buildObjectForResourceResponse(response, loader); bool isNotModified = response.httpStatusCode() == 304; CachedResource* cachedResource = 0; if (resourceLoader && !isNotModified) cachedResource = resourceLoader->cachedResource(); if (!cachedResource) cachedResource = InspectorPageAgent::cachedResource(loader->frame(), response.url()); if (cachedResource) { // Use mime type from cached resource in case the one in response is empty. if (resourceResponse && response.mimeType().isEmpty()) resourceResponse->setString(TypeBuilder::Network::Response::MimeType, cachedResource->response().mimeType()); m_resourcesData->addCachedResource(requestId, cachedResource); } InspectorPageAgent::ResourceType type = cachedResource ? InspectorPageAgent::cachedResourceType(*cachedResource) : InspectorPageAgent::OtherResource; if (m_loadingXHRSynchronously || m_resourcesData->resourceType(requestId) == InspectorPageAgent::XHRResource) type = InspectorPageAgent::XHRResource; else if (m_resourcesData->resourceType(requestId) == InspectorPageAgent::ScriptResource) type = InspectorPageAgent::ScriptResource; else if (equalIgnoringFragmentIdentifier(response.url(), loader->url()) && !loader->isCommitted()) type = InspectorPageAgent::DocumentResource; m_resourcesData->responseReceived(requestId, m_pageAgent->frameId(loader->frame()), response); m_resourcesData->setResourceType(requestId, type); m_frontend->responseReceived(requestId, m_pageAgent->frameId(loader->frame()), m_pageAgent->loaderId(loader), currentTime(), InspectorPageAgent::resourceTypeJson(type), resourceResponse); // If we revalidated the resource and got Not modified, send content length following didReceiveResponse // as there will be no calls to didReceiveData from the network stack. if (isNotModified && cachedResource && cachedResource->encodedSize()) didReceiveData(identifier, 0, cachedResource->encodedSize(), 0); }
void InspectorResourceAgent::didReceiveResponse(unsigned long identifier, DocumentLoader* loader, const ResourceResponse& response) { RefPtr<InspectorObject> resourceResponse = buildObjectForResourceResponse(response); String type = "Other"; if (loader) { if (equalIgnoringFragmentIdentifier(response.url(), loader->frameLoader()->iconURL())) type = "Image"; else { CachedResource* cachedResource = InspectorResourceAgent::cachedResource(loader->frame(), response.url()); if (cachedResource) type = cachedResourceTypeString(*cachedResource); if (equalIgnoringFragmentIdentifier(response.url(), loader->url()) && type == "Other") type = "Document"; // Use mime type from cached resource in case the one in response is empty. if (response.mimeType().isEmpty() && cachedResource) resourceResponse->setString("mimeType", cachedResource->response().mimeType()); } } m_frontend->didReceiveResponse(identifier, currentTime(), type, resourceResponse); }
HRESULT WebDataSource::subresourceForURL(_In_ BSTR url, _COM_Outptr_opt_ IWebResource** resource) { if (!resource) { ASSERT_NOT_REACHED(); return E_POINTER; } *resource = nullptr; if (!m_loader) return E_UNEXPECTED; Document* doc = m_loader->frameLoader()->frame().document(); if (!doc) return E_FAIL; CachedResource* cachedResource = doc->cachedResourceLoader().cachedResource(String(url)); if (!cachedResource) return E_FAIL; *resource = WebResource::createInstance(cachedResource->resourceBuffer(), cachedResource->response()); return S_OK; }
void InspectorResourceAgent::didReceiveResponse(unsigned long identifier, DocumentLoader* loader, const ResourceResponse& response) { String requestId = IdentifiersFactory::requestId(identifier); RefPtr<InspectorObject> resourceResponse = buildObjectForResourceResponse(response, loader); InspectorPageAgent::ResourceType type = InspectorPageAgent::OtherResource; long cachedResourceSize = 0; if (loader) { CachedResource* cachedResource = InspectorPageAgent::cachedResource(loader->frame(), response.url()); if (cachedResource) { type = InspectorPageAgent::cachedResourceType(*cachedResource); cachedResourceSize = cachedResource->encodedSize(); // Use mime type from cached resource in case the one in response is empty. if (resourceResponse && response.mimeType().isEmpty()) resourceResponse->setString("mimeType", cachedResource->response().mimeType()); m_resourcesData->addCachedResource(requestId, cachedResource); } if (m_loadingXHRSynchronously || m_resourcesData->resourceType(requestId) == InspectorPageAgent::XHRResource) type = InspectorPageAgent::XHRResource; else if (m_resourcesData->resourceType(requestId) == InspectorPageAgent::ScriptResource) type = InspectorPageAgent::ScriptResource; else if (equalIgnoringFragmentIdentifier(response.url(), loader->frameLoader()->icon()->url())) type = InspectorPageAgent::ImageResource; else if (equalIgnoringFragmentIdentifier(response.url(), loader->url()) && !loader->isCommitted()) type = InspectorPageAgent::DocumentResource; m_resourcesData->responseReceived(requestId, m_pageAgent->frameId(loader->frame()), response); } m_resourcesData->setResourceType(requestId, type); m_frontend->responseReceived(requestId, m_pageAgent->frameId(loader->frame()), m_pageAgent->loaderId(loader), currentTime(), InspectorPageAgent::resourceTypeString(type), resourceResponse); // If we revalidated the resource and got Not modified, send content length following didReceiveResponse // as there will be no calls to didReceiveData from the network stack. if (cachedResourceSize && response.httpStatusCode() == 304) didReceiveData(identifier, 0, cachedResourceSize, 0); }
PassRefPtr<LegacyWebArchive> LegacyWebArchive::create(const String& markupString, Frame* frame, const Vector<Node*>& nodes, FrameFilter* frameFilter) { ASSERT(frame); const ResourceResponse& response = frame->loader().documentLoader()->response(); URL responseURL = response.url(); // it's possible to have a response without a URL here // <rdar://problem/5454935> if (responseURL.isNull()) responseURL = URL(ParsedURLString, emptyString()); RefPtr<ArchiveResource> mainResource = ArchiveResource::create(utf8Buffer(markupString), responseURL, response.mimeType(), "UTF-8", frame->tree().uniqueName()); Vector<PassRefPtr<LegacyWebArchive>> subframeArchives; Vector<PassRefPtr<ArchiveResource>> subresources; HashSet<URL> uniqueSubresources; size_t nodesSize = nodes.size(); for (size_t i = 0; i < nodesSize; ++i) { Node& node = *nodes[i]; Frame* childFrame; if ((isHTMLFrameElement(node) || isHTMLIFrameElement(node) || isHTMLObjectElement(node)) && (childFrame = toHTMLFrameOwnerElement(node).contentFrame())) { if (frameFilter && !frameFilter->shouldIncludeSubframe(childFrame)) continue; RefPtr<LegacyWebArchive> subframeArchive = create(childFrame->document(), frameFilter); if (subframeArchive) subframeArchives.append(subframeArchive); else LOG_ERROR("Unabled to archive subframe %s", childFrame->tree().uniqueName().string().utf8().data()); } else { ListHashSet<URL> subresourceURLs; node.getSubresourceURLs(subresourceURLs); DocumentLoader* documentLoader = frame->loader().documentLoader(); ListHashSet<URL>::iterator iterEnd = subresourceURLs.end(); for (ListHashSet<URL>::iterator iter = subresourceURLs.begin(); iter != iterEnd; ++iter) { const URL& subresourceURL = *iter; if (uniqueSubresources.contains(subresourceURL)) continue; uniqueSubresources.add(subresourceURL); RefPtr<ArchiveResource> resource = documentLoader->subresource(subresourceURL); if (resource) { subresources.append(resource.release()); continue; } ResourceRequest request(subresourceURL); #if ENABLE(CACHE_PARTITIONING) request.setCachePartition(frame->document()->topOrigin()->cachePartition()); #endif CachedResource* cachedResource = memoryCache()->resourceForRequest(request); if (cachedResource) { ResourceBuffer* data = cachedResource->resourceBuffer(); resource = ArchiveResource::create(data ? data->sharedBuffer() : 0, subresourceURL, cachedResource->response()); if (resource) { subresources.append(resource.release()); continue; } } // FIXME: should do something better than spew to console here LOG_ERROR("Failed to archive subresource for %s", subresourceURL.string().utf8().data()); } } } // Add favicon if one exists for this page, if we are archiving the entire page. if (nodesSize && nodes[0]->isDocumentNode() && iconDatabase().isEnabled()) { const String& iconURL = iconDatabase().synchronousIconURLForPageURL(responseURL); if (!iconURL.isEmpty() && iconDatabase().synchronousIconDataKnownForIconURL(iconURL)) { if (Image* iconImage = iconDatabase().synchronousIconForPageURL(responseURL, IntSize(16, 16))) { if (RefPtr<ArchiveResource> resource = ArchiveResource::create(iconImage->data(), URL(ParsedURLString, iconURL), "image/x-icon", "", "")) subresources.append(resource.release()); } } } return create(mainResource.release(), subresources, subframeArchives); }
PassRefPtr<LegacyWebArchive> LegacyWebArchive::create(const String& markupString, Frame* frame, Vector<Node*>& nodes) { ASSERT(frame); const ResourceResponse& response = frame->loader()->documentLoader()->response(); KURL responseURL = response.url(); // it's possible to have a response without a URL here // <rdar://problem/5454935> if (responseURL.isNull()) responseURL = KURL(""); PassRefPtr<ArchiveResource> mainResource = ArchiveResource::create(utf8Buffer(markupString), responseURL, response.mimeType(), "UTF-8", frame->tree()->name()); Vector<PassRefPtr<LegacyWebArchive> > subframeArchives; Vector<PassRefPtr<ArchiveResource> > subresources; HashSet<KURL> uniqueSubresources; Vector<Node*>::iterator it = nodes.begin(); Vector<Node*>::iterator end = nodes.end(); for (; it != end; ++it) { Frame* childFrame; if (((*it)->hasTagName(HTMLNames::frameTag) || (*it)->hasTagName(HTMLNames::iframeTag) || (*it)->hasTagName(HTMLNames::objectTag)) && (childFrame = static_cast<HTMLFrameOwnerElement*>(*it)->contentFrame())) { RefPtr<LegacyWebArchive> subframeArchive; if (Document* document = childFrame->document()) subframeArchive = LegacyWebArchive::create(document); else subframeArchive = create(childFrame); if (subframeArchive) subframeArchives.append(subframeArchive); else LOG_ERROR("Unabled to archive subframe %s", childFrame->tree()->name().string().utf8().data()); } else { ListHashSet<KURL> subresourceURLs; (*it)->getSubresourceURLs(subresourceURLs); DocumentLoader* documentLoader = frame->loader()->documentLoader(); ListHashSet<KURL>::iterator iterEnd = subresourceURLs.end(); for (ListHashSet<KURL>::iterator iter = subresourceURLs.begin(); iter != iterEnd; ++iter) { const KURL& subresourceURL = *iter; if (uniqueSubresources.contains(subresourceURL)) continue; uniqueSubresources.add(subresourceURL); RefPtr<ArchiveResource> resource = documentLoader->subresource(subresourceURL); if (resource) { subresources.append(resource.release()); continue; } CachedResource *cachedResource = cache()->resourceForURL(subresourceURL); if (cachedResource) { resource = ArchiveResource::create(cachedResource->data(), subresourceURL, cachedResource->response()); if (resource) { subresources.append(resource.release()); continue; } } // FIXME: should do something better than spew to console here LOG_ERROR("Failed to archive subresource for %s", subresourceURL.string().utf8().data()); } } } return create(mainResource, subresources, subframeArchives); }
void CachedResource::load(CachedResourceLoader* cachedResourceLoader, const ResourceLoaderOptions& options) { if (!cachedResourceLoader->frame()) { failBeforeStarting(); return; } FrameLoader& frameLoader = cachedResourceLoader->frame()->loader(); if (options.securityCheck() == DoSecurityCheck && (frameLoader.state() == FrameStateProvisional || !frameLoader.activeDocumentLoader() || frameLoader.activeDocumentLoader()->isStopping())) { failBeforeStarting(); return; } m_options = options; m_loading = true; #if USE(QUICK_LOOK) if (!m_resourceRequest.isNull() && m_resourceRequest.url().protocolIs(QLPreviewProtocol())) { // When QuickLook is invoked to convert a document, it returns a unique URL in the // NSURLReponse for the main document. To make safeQLURLForDocumentURLAndResourceURL() // work, we need to use the QL URL not the original URL. const URL& documentURL = cachedResourceLoader->frame() ? cachedResourceLoader->frame()->loader().documentLoader()->response().url() : cachedResourceLoader->document()->url(); m_resourceRequest.setURL(safeQLURLForDocumentURLAndResourceURL(documentURL, url())); } #endif if (!accept().isEmpty()) m_resourceRequest.setHTTPAccept(accept()); if (isCacheValidator()) { CachedResource* resourceToRevalidate = m_resourceToRevalidate; ASSERT(resourceToRevalidate->canUseCacheValidator()); ASSERT(resourceToRevalidate->isLoaded()); const String& lastModified = resourceToRevalidate->response().httpHeaderField(HTTPHeaderName::LastModified); const String& eTag = resourceToRevalidate->response().httpHeaderField(HTTPHeaderName::ETag); if (!lastModified.isEmpty() || !eTag.isEmpty()) { ASSERT(cachedResourceLoader->cachePolicy(type()) != CachePolicyReload); if (cachedResourceLoader->cachePolicy(type()) == CachePolicyRevalidate) m_resourceRequest.setHTTPHeaderField(HTTPHeaderName::CacheControl, "max-age=0"); if (!lastModified.isEmpty()) m_resourceRequest.setHTTPHeaderField(HTTPHeaderName::IfModifiedSince, lastModified); if (!eTag.isEmpty()) m_resourceRequest.setHTTPHeaderField(HTTPHeaderName::IfNoneMatch, eTag); } } #if ENABLE(LINK_PREFETCH) if (type() == CachedResource::LinkPrefetch || type() == CachedResource::LinkSubresource) m_resourceRequest.setHTTPHeaderField(HTTPHeaderName::Purpose, "prefetch"); #endif m_resourceRequest.setPriority(loadPriority()); if (type() != MainResource) addAdditionalRequestHeaders(cachedResourceLoader); // FIXME: It's unfortunate that the cache layer and below get to know anything about fragment identifiers. // We should look into removing the expectation of that knowledge from the platform network stacks. ResourceRequest request(m_resourceRequest); if (!m_fragmentIdentifierForRequest.isNull()) { URL url = request.url(); url.setFragmentIdentifier(m_fragmentIdentifierForRequest); request.setURL(url); m_fragmentIdentifierForRequest = String(); } m_loader = platformStrategies()->loaderStrategy()->resourceLoadScheduler()->scheduleSubresourceLoad(cachedResourceLoader->frame(), this, request, request.priority(), options); if (!m_loader) { failBeforeStarting(); return; } m_status = Pending; }
void Loader::Host::servePendingRequests(RequestQueue& requestsPending, bool& serveLowerPriority) { while (!requestsPending.isEmpty()) { Request* request = requestsPending.first(); DocLoader* docLoader = request->docLoader(); bool resourceIsCacheValidator = request->cachedResource()->isCacheValidator(); // If the document is fully parsed and there are no pending stylesheets there won't be any more // resources that we would want to push to the front of the queue. Just hand off the remaining resources // to the networking layer. bool parsedAndStylesheetsKnown = !docLoader->doc()->parsing() && docLoader->doc()->haveStylesheetsLoaded(); if (!parsedAndStylesheetsKnown && !resourceIsCacheValidator && m_requestsLoading.size() >= m_maxRequestsInFlight) { serveLowerPriority = false; return; } requestsPending.removeFirst(); ResourceRequest resourceRequest(request->cachedResource()->url()); if (!request->cachedResource()->accept().isEmpty()) resourceRequest.setHTTPAccept(request->cachedResource()->accept()); KURL referrer = docLoader->doc()->url(); if ((referrer.protocolIs("http") || referrer.protocolIs("https")) && referrer.path().isEmpty()) referrer.setPath("/"); resourceRequest.setHTTPReferrer(referrer.string()); FrameLoader::addHTTPOriginIfNeeded(resourceRequest, docLoader->doc()->securityOrigin()->toString()); if (resourceIsCacheValidator) { CachedResource* resourceToRevalidate = request->cachedResource()->resourceToRevalidate(); ASSERT(resourceToRevalidate->canUseCacheValidator()); ASSERT(resourceToRevalidate->isLoaded()); const String& lastModified = resourceToRevalidate->response().httpHeaderField("Last-Modified"); const String& eTag = resourceToRevalidate->response().httpHeaderField("ETag"); if (!lastModified.isEmpty() || !eTag.isEmpty()) { ASSERT(docLoader->cachePolicy() != CachePolicyReload); if (docLoader->cachePolicy() == CachePolicyRevalidate) resourceRequest.setHTTPHeaderField("Cache-Control", "max-age=0"); if (!lastModified.isEmpty()) resourceRequest.setHTTPHeaderField("If-Modified-Since", lastModified); if (!eTag.isEmpty()) resourceRequest.setHTTPHeaderField("If-None-Match", eTag); } } RefPtr<SubresourceLoader> loader = SubresourceLoader::create(docLoader->doc()->frame(), this, resourceRequest, request->shouldSkipCanLoadCheck(), request->sendResourceLoadCallbacks()); if (loader) { m_requestsLoading.add(loader.release(), request); request->cachedResource()->setRequestedFromNetworkingLayer(); #if REQUEST_DEBUG printf("HOST %s COUNT %d LOADING %s\n", resourceRequest.url().host().latin1().data(), m_requestsLoading.size(), request->cachedResource()->url().latin1().data()); #endif } else { docLoader->decrementRequestCount(); docLoader->setLoadInProgress(true); request->cachedResource()->error(); docLoader->setLoadInProgress(false); delete request; } } }
void InspectorResourceAgent::didReceiveResponse(unsigned long identifier, DocumentLoader* loader, const ResourceResponse& response, ResourceLoader* resourceLoader) { if (m_hiddenRequestIdentifiers.contains(identifier)) return; String requestId = IdentifiersFactory::requestId(identifier); RefPtr<Inspector::Protocol::Network::Response> resourceResponse = buildObjectForResourceResponse(response, loader); bool isNotModified = response.httpStatusCode() == 304; CachedResource* cachedResource = nullptr; if (resourceLoader && resourceLoader->isSubresourceLoader() && !isNotModified) cachedResource = static_cast<SubresourceLoader*>(resourceLoader)->cachedResource(); if (!cachedResource) cachedResource = InspectorPageAgent::cachedResource(loader->frame(), response.url()); if (cachedResource) { // Use mime type from cached resource in case the one in response is empty. if (resourceResponse && response.mimeType().isEmpty()) resourceResponse->setString(Inspector::Protocol::Network::Response::MimeType, cachedResource->response().mimeType()); m_resourcesData->addCachedResource(requestId, cachedResource); } InspectorPageAgent::ResourceType type = m_resourcesData->resourceType(requestId); InspectorPageAgent::ResourceType newType = cachedResource ? InspectorPageAgent::cachedResourceType(*cachedResource) : type; // FIXME: XHRResource is returned for CachedResource::RawResource, it should be OtherResource unless it truly is an XHR. // RawResource is used for loading worker scripts, and those should stay as ScriptResource and not change to XHRResource. if (type != newType && newType != InspectorPageAgent::XHRResource && newType != InspectorPageAgent::OtherResource) type = newType; m_resourcesData->responseReceived(requestId, m_pageAgent->frameId(loader->frame()), response); m_resourcesData->setResourceType(requestId, type); m_frontendDispatcher->responseReceived(requestId, m_pageAgent->frameId(loader->frame()), m_pageAgent->loaderId(loader), currentTime(), InspectorPageAgent::resourceTypeJson(type), resourceResponse); // If we revalidated the resource and got Not modified, send content length following didReceiveResponse // as there will be no calls to didReceiveData from the network stack. if (isNotModified && cachedResource && cachedResource->encodedSize()) didReceiveData(identifier, nullptr, cachedResource->encodedSize(), 0); }
PassRefPtr<LegacyWebArchive> LegacyWebArchive::create(const String& markupString, Frame* frame, const Vector<Node*>& nodes) { ASSERT(frame); const ResourceResponse& response = frame->loader()->documentLoader()->response(); KURL responseURL = response.url(); // it's possible to have a response without a URL here // <rdar://problem/5454935> if (responseURL.isNull()) responseURL = KURL(ParsedURLString, ""); PassRefPtr<ArchiveResource> mainResource = ArchiveResource::create(utf8Buffer(markupString), responseURL, response.mimeType(), "UTF-8", frame->tree()->uniqueName()); Vector<PassRefPtr<LegacyWebArchive> > subframeArchives; Vector<PassRefPtr<ArchiveResource> > subresources; HashSet<KURL> uniqueSubresources; size_t nodesSize = nodes.size(); for (size_t i = 0; i < nodesSize; ++i) { Node* node = nodes[i]; Frame* childFrame; if ((node->hasTagName(HTMLNames::frameTag) || node->hasTagName(HTMLNames::iframeTag) || node->hasTagName(HTMLNames::objectTag)) && (childFrame = static_cast<HTMLFrameOwnerElement*>(node)->contentFrame())) { RefPtr<LegacyWebArchive> subframeArchive = create(childFrame->document()); if (subframeArchive) subframeArchives.append(subframeArchive); else LOG_ERROR("Unabled to archive subframe %s", childFrame->tree()->uniqueName().string().utf8().data()); } else { ListHashSet<KURL> subresourceURLs; node->getSubresourceURLs(subresourceURLs); DocumentLoader* documentLoader = frame->loader()->documentLoader(); ListHashSet<KURL>::iterator iterEnd = subresourceURLs.end(); for (ListHashSet<KURL>::iterator iter = subresourceURLs.begin(); iter != iterEnd; ++iter) { const KURL& subresourceURL = *iter; if (uniqueSubresources.contains(subresourceURL)) continue; uniqueSubresources.add(subresourceURL); RefPtr<ArchiveResource> resource = documentLoader->subresource(subresourceURL); if (resource) { subresources.append(resource.release()); continue; } CachedResource* cachedResource = memoryCache()->resourceForURL(subresourceURL); if (cachedResource) { resource = ArchiveResource::create(cachedResource->data(), subresourceURL, cachedResource->response()); if (resource) { subresources.append(resource.release()); continue; } } // FIXME: should do something better than spew to console here LOG_ERROR("Failed to archive subresource for %s", subresourceURL.string().utf8().data()); } } } // Add favicon if one exists for this page, if we are archiving the entire page. if (nodesSize && nodes[0]->isDocumentNode() && iconDatabase().isEnabled()) { const String& iconURL = iconDatabase().synchronousIconURLForPageURL(responseURL); if (!iconURL.isEmpty() && iconDatabase().synchronousIconDataKnownForIconURL(iconURL)) { if (Image* iconImage = iconDatabase().synchronousIconForPageURL(responseURL, IntSize(16, 16))) { if (RefPtr<ArchiveResource> resource = ArchiveResource::create(iconImage->data(), KURL(ParsedURLString, iconURL), "image/x-icon", "", "")) subresources.append(resource.release()); } } } return create(mainResource, subresources, subframeArchives); }
static PassRefPtr<TypeBuilder::Network::CachedResource> buildObjectForCachedResource(const CachedResource& cachedResource, DocumentLoader* loader) { RefPtr<TypeBuilder::Network::CachedResource> resourceObject = TypeBuilder::Network::CachedResource::create() .setUrl(cachedResource.url()) .setType(InspectorPageAgent::cachedResourceTypeJson(cachedResource)) .setBodySize(cachedResource.encodedSize()); RefPtr<TypeBuilder::Network::Response> resourceResponse = buildObjectForResourceResponse(cachedResource.response(), loader); if (resourceResponse) resourceObject->setResponse(resourceResponse); return resourceObject; }