CachedResource* CachedResourceLoader::requestResource(CachedResource::Type type, const String& resourceURL, const String& charset, ResourceLoadPriority priority, bool forPreload) { KURL url = m_document->completeURL(resourceURL); LOG(ResourceLoading, "CachedResourceLoader::requestResource '%s', charset '%s', priority=%d, forPreload=%u", url.string().latin1().data(), charset.latin1().data(), priority, forPreload); // If only the fragment identifiers differ, it is the same resource. url = MemoryCache::removeFragmentIdentifierIfNeeded(url); if (!url.isValid()) return 0; if (!canRequest(type, url)) return 0; // FIXME: Figure out what is the correct way to merge this security check with the one above. if (!document()->securityOrigin()->canDisplay(url)) { if (!forPreload) FrameLoader::reportLocalLoadFailed(document()->frame(), url.string()); LOG(ResourceLoading, "CachedResourceLoader::requestResource URL was not allowed by SecurityOrigin::canDisplay"); return 0; } if (memoryCache()->disabled()) { DocumentResourceMap::iterator it = m_documentResources.find(url.string()); if (it != m_documentResources.end()) { it->second->setOwningCachedResourceLoader(0); m_documentResources.remove(it); } } // See if we can use an existing resource from the cache. CachedResource* resource = memoryCache()->resourceForURL(url); switch (determineRevalidationPolicy(type, forPreload, resource)) { case Load: resource = loadResource(type, url, charset, priority); break; case Reload: memoryCache()->remove(resource); resource = loadResource(type, url, charset, priority); break; case Revalidate: resource = revalidateResource(resource, priority); break; case Use: memoryCache()->resourceAccessed(resource); notifyLoadedFromMemoryCache(resource); break; } if (!resource) return 0; ASSERT(resource->url() == url.string()); m_documentResources.set(resource->url(), resource); return resource; }
CachedResource* CachedResourceLoader::requestResource(CachedResource::Type type, ResourceRequest& request, const String& charset, ResourceLoadPriority priority, bool forPreload) { KURL url = request.url(); LOG(ResourceLoading, "CachedResourceLoader::requestResource '%s', charset '%s', priority=%d, forPreload=%u", url.string().latin1().data(), charset.latin1().data(), priority, forPreload); // If only the fragment identifiers differ, it is the same resource. url = MemoryCache::removeFragmentIdentifierIfNeeded(url); if (!url.isValid()) return 0; if (!canRequest(type, url, forPreload)) return 0; if (memoryCache()->disabled()) { DocumentResourceMap::iterator it = m_documentResources.find(url.string()); if (it != m_documentResources.end()) { it->second->setOwningCachedResourceLoader(0); m_documentResources.remove(it); } } // See if we can use an existing resource from the cache. CachedResource* resource = memoryCache()->resourceForURL(url); if (request.url() != url) request.setURL(url); switch (determineRevalidationPolicy(type, forPreload, resource)) { case Load: resource = loadResource(type, request, charset, priority); break; case Reload: memoryCache()->remove(resource); resource = loadResource(type, request, charset, priority); break; case Revalidate: resource = revalidateResource(resource, priority); break; case Use: memoryCache()->resourceAccessed(resource); notifyLoadedFromMemoryCache(resource); break; } if (!resource) return 0; ASSERT(resource->url() == url.string()); m_documentResources.set(resource->url(), resource); return resource; }
void MemoryCache::removeResourcesWithOrigin(SecurityOrigin* origin) { Vector<CachedResource*> resourcesWithOrigin; CachedResourceMap::iterator e = m_resources.end(); #if ENABLE(CACHE_PARTITIONING) String originPartition = ResourceRequest::partitionName(origin->host()); #endif for (CachedResourceMap::iterator it = m_resources.begin(); it != e; ++it) { #if ENABLE(CACHE_PARTITIONING) for (CachedResourceItem::iterator itemIterator = it->value->begin(); itemIterator != it->value->end(); ++itemIterator) { CachedResource* resource = itemIterator->value; String partition = itemIterator->key; if (partition == originPartition) { resourcesWithOrigin.append(resource); continue; } #else CachedResource* resource = it->value; #endif RefPtr<SecurityOrigin> resourceOrigin = SecurityOrigin::createFromString(resource->url()); if (!resourceOrigin) continue; if (resourceOrigin->equal(origin)) resourcesWithOrigin.append(resource); #if ENABLE(CACHE_PARTITIONING) } #endif } for (size_t i = 0; i < resourcesWithOrigin.size(); ++i) remove(resourcesWithOrigin[i]); }
CachedResource* DocLoader::requestResource(CachedResource::Type type, const String& url, const String* charset, bool skipCanLoadCheck, bool sendResourceLoadCallbacks) { KURL fullURL = m_doc->completeURL(url.deprecatedString()); if (cache()->disabled()) { HashMap<String, CachedResource*>::iterator it = m_docResources.find(fullURL.url()); if (it != m_docResources.end()) { it->second->setDocLoader(0); m_docResources.remove(it); } } if (m_frame && m_frame->loader()->isReloading()) setCachePolicy(CachePolicyReload); checkForReload(fullURL); CachedResource* resource = cache()->requestResource(this, type, fullURL, charset, skipCanLoadCheck, sendResourceLoadCallbacks); if (resource) { m_docResources.set(resource->url(), resource); checkCacheObjectStatus(resource); } return resource; }
static PassRefPtr<InspectorObject> 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); const CachedResourceLoader::DocumentResourceMap& allResources = frame->document()->cachedResourceLoader()->allCachedResources(); CachedResourceLoader::DocumentResourceMap::const_iterator end = allResources.end(); for (CachedResourceLoader::DocumentResourceMap::const_iterator it = allResources.begin(); it != end; ++it) { CachedResource* cachedResource = it->second.get(); RefPtr<InspectorObject> resourceObject = InspectorObject::create(); resourceObject->setString("url", cachedResource->url()); resourceObject->setString("type", cachedResourceTypeString(*cachedResource)); 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::didFinishLoading(SubresourceLoader* loader) { RequestMap::iterator i = m_requestsLoading.find(loader); if (i == m_requestsLoading.end()) return; Request* request = i->second; m_requestsLoading.remove(i); DocLoader* docLoader = request->docLoader(); if (!request->isMultipart()) docLoader->decrementRequestCount(); CachedResource* resource = request->cachedResource(); // If we got a 4xx response, we're pretending to have received a network // error, so we can't send the successful data() and finish() callbacks. if (!resource->errorOccurred()) { docLoader->setLoadInProgress(true); resource->data(loader->resourceData(), true); resource->finish(); } delete request; docLoader->setLoadInProgress(false); #if REQUEST_DEBUG KURL u(resource->url()); printf("HOST %s COUNT %d RECEIVED %s\n", u.host().latin1().data(), m_requestsLoading.size(), resource->url().latin1().data()); #endif servePendingRequests(); }
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 CachedResourceLoader::printPreloadStats() { unsigned scripts = 0; unsigned scriptMisses = 0; unsigned stylesheets = 0; unsigned stylesheetMisses = 0; unsigned images = 0; unsigned imageMisses = 0; ListHashSet<CachedResource*>::iterator end = m_preloads.end(); for (ListHashSet<CachedResource*>::iterator it = m_preloads.begin(); it != end; ++it) { CachedResource* res = *it; if (res->preloadResult() == CachedResource::PreloadNotReferenced) printf("!! UNREFERENCED PRELOAD %s\n", res->url().latin1().data()); else if (res->preloadResult() == CachedResource::PreloadReferencedWhileComplete) printf("HIT COMPLETE PRELOAD %s\n", res->url().latin1().data()); else if (res->preloadResult() == CachedResource::PreloadReferencedWhileLoading) printf("HIT LOADING PRELOAD %s\n", res->url().latin1().data()); if (res->type() == CachedResource::Script) { scripts++; if (res->preloadResult() < CachedResource::PreloadReferencedWhileLoading) scriptMisses++; } else if (res->type() == CachedResource::CSSStyleSheet) { stylesheets++; if (res->preloadResult() < CachedResource::PreloadReferencedWhileLoading) stylesheetMisses++; } else { images++; if (res->preloadResult() < CachedResource::PreloadReferencedWhileLoading) imageMisses++; } if (res->errorOccurred()) memoryCache()->remove(res); res->decreasePreloadCount(); } m_preloads.clear(); if (scripts) printf("SCRIPTS: %d (%d hits, hit rate %d%%)\n", scripts, scripts - scriptMisses, (scripts - scriptMisses) * 100 / scripts); if (stylesheets) printf("STYLESHEETS: %d (%d hits, hit rate %d%%)\n", stylesheets, stylesheets - stylesheetMisses, (stylesheets - stylesheetMisses) * 100 / stylesheets); if (images) printf("IMAGES: %d (%d hits, hit rate %d%%)\n", images, images - imageMisses, (images - imageMisses) * 100 / images); }
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; }
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; }
bool MemoryCache::add(CachedResource& resource) { if (disabled()) return false; ASSERT(WTF::isMainThread()); #if ENABLE(CACHE_PARTITIONING) auto key = std::make_pair(resource.url(), resource.cachePartition()); #else auto& key = resource.url(); #endif ensureSessionResourceMap(resource.sessionID()).set(key, &resource); resource.setInCache(true); resourceAccessed(resource); LOG(ResourceLoading, "MemoryCache::add Added '%s', resource %p\n", resource.url().string().latin1().data(), &resource); return true; }
void DocLoader::requestPreload(CachedResource::Type type, const String& url, const String& charset) { String encoding; if (type == CachedResource::Script || type == CachedResource::CSSStyleSheet) encoding = charset.isEmpty() ? m_doc->frame()->loader()->encoding() : charset; CachedResource* resource = requestResource(type, url, encoding, true); if (!resource || m_preloads.contains(resource)) return; resource->increasePreloadCount(); m_preloads.add(resource); #if PRELOAD_DEBUG printf("PRELOADING %s\n", resource->url().latin1().data()); #endif }
void CachedResourceLoader::requestPreload(CachedResource::Type type, ResourceRequest& request, const String& charset) { String encoding; if (type == CachedResource::Script || type == CachedResource::CSSStyleSheet) encoding = charset.isEmpty() ? m_document->charset() : charset; CachedResource* resource = requestResource(type, request, encoding, defaultCachedResourceOptions(), ResourceLoadPriorityUnresolved, true); if (!resource || (m_preloads && m_preloads->contains(resource))) return; resource->increasePreloadCount(); if (!m_preloads) m_preloads = adoptPtr(new ListHashSet<CachedResource*>); m_preloads->add(resource); #if PRELOAD_DEBUG printf("PRELOADING %s\n", resource->url().latin1().data()); #endif }
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); }
bool CachedResourceLoader::isPreloaded(const String& urlString) const { const KURL& url = m_document->completeURL(urlString); if (m_preloads) { ListHashSet<CachedResource*>::iterator end = m_preloads->end(); for (ListHashSet<CachedResource*>::iterator it = m_preloads->begin(); it != end; ++it) { CachedResource* resource = *it; if (resource->url() == url) return true; } } Deque<PendingPreload>::const_iterator dequeEnd = m_pendingPreloads.end(); for (Deque<PendingPreload>::const_iterator it = m_pendingPreloads.begin(); it != dequeEnd; ++it) { PendingPreload pendingPreload = *it; if (pendingPreload.m_request.url() == url) return true; } return false; }
void Loader::Host::didFinishLoading(SubresourceLoader* loader) { RefPtr<Host> myProtector(this); RequestMap::iterator i = m_requestsLoading.find(loader); if (i == m_requestsLoading.end()) return; Request* request = i->second; m_requestsLoading.remove(i); DocLoader* docLoader = request->docLoader(); // Prevent the document from being destroyed before we are done with // the docLoader that it will delete when the document gets deleted. RefPtr<Document> protector(docLoader->doc()); if (!request->isMultipart()) docLoader->decrementRequestCount(); CachedResource* resource = request->cachedResource(); ASSERT(!resource->resourceToRevalidate()); // If we got a 4xx response, we're pretending to have received a network // error, so we can't send the successful data() and finish() callbacks. if (!resource->errorOccurred()) { docLoader->setLoadInProgress(true); resource->data(loader->resourceData(), true); resource->finish(); } delete request; docLoader->setLoadInProgress(false); docLoader->checkForPendingPreloads(); #if REQUEST_DEBUG KURL u(ParsedURLString, resource->url()); printf("HOST %s COUNT %d RECEIVED %s\n", u.host().latin1().data(), m_requestsLoading.size(), resource->url().latin1().data()); #endif servePendingRequests(); }
void InspectorPageAgent::searchInResources(ErrorString*, const String& text, const bool* const optionalCaseSensitive, const bool* const optionalIsRegex, RefPtr<InspectorArray>* object) { RefPtr<InspectorArray> result = InspectorArray::create(); bool isRegex = optionalIsRegex ? *optionalIsRegex : false; String regexSource = isRegex ? text : createSearchRegexSource(text); bool caseSensitive = optionalCaseSensitive ? *optionalCaseSensitive : false; RegularExpression regex(regexSource, caseSensitive ? TextCaseSensitive : TextCaseInsensitive); for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext(m_page->mainFrame())) { String content; bool base64Encoded; Vector<CachedResource*> allResources = cachedResourcesForFrame(frame); for (Vector<CachedResource*>::const_iterator it = allResources.begin(); it != allResources.end(); ++it) { CachedResource* cachedResource = *it; switch (InspectorPageAgent::cachedResourceType(*cachedResource)) { case InspectorPageAgent::StylesheetResource: case InspectorPageAgent::ScriptResource: if (cachedResourceContent(cachedResource, &content, &base64Encoded)) { ASSERT(!base64Encoded); int matchesCount = countRegularExpressionMatches(regex, content); if (matchesCount) result->pushValue(buildObjectForSearchMatch(frameId(frame), cachedResource->url(), matchesCount)); } break; default: break; } } if (mainResourceContent(frame, false, &content)) { int matchesCount = countRegularExpressionMatches(regex, content); if (matchesCount) result->pushValue(buildObjectForSearchMatch(frameId(frame), frame->document()->url(), matchesCount)); } } *object = result; }
void MemoryCache::revalidationSucceeded(CachedResource* revalidatingResource, const ResourceResponse& response) { CachedResource* resource = revalidatingResource->resourceToRevalidate(); ASSERT(resource); ASSERT(!resource->inCache()); ASSERT(resource->isLoaded()); ASSERT(revalidatingResource->inCache()); // Calling evict() can potentially delete revalidatingResource, which we use // below. This mustn't be the case since revalidation means it is loaded // and so canDelete() is false. ASSERT(!revalidatingResource->canDelete()); evict(revalidatingResource); CachedResourceMap& resources = getSessionMap(resource->sessionID()); #if ENABLE(CACHE_PARTITIONING) ASSERT(!resources.get(resource->url()) || !resources.get(resource->url())->get(resource->cachePartition())); CachedResourceItem* originMap = resources.get(resource->url()); if (!originMap) { originMap = new CachedResourceItem; resources.set(resource->url(), adoptPtr(originMap)); } originMap->set(resource->cachePartition(), resource); #else ASSERT(!resources.get(resource->url())); resources.set(resource->url(), resource); #endif resource->setInCache(true); resource->updateResponseAfterRevalidation(response); insertInLRUList(resource); int delta = resource->size(); if (resource->decodedSize() && resource->hasClients()) insertInLiveDecodedResourcesList(resource); if (delta) adjustSize(resource->hasClients(), delta); revalidatingResource->switchClientsToRevalidatedResource(); ASSERT(!revalidatingResource->m_deleted); // this deletes the revalidating resource revalidatingResource->clearResourceToRevalidate(); }
void CachedResourceLoader::reloadImagesIfNotDeferred() { DocumentResourceMap::iterator end = m_documentResources.end(); for (DocumentResourceMap::iterator it = m_documentResources.begin(); it != end; ++it) { CachedResource* resource = it->value.get(); if (resource->type() == CachedResource::ImageResource && resource->stillNeedsLoad() && !clientDefersImage(resource->url())) const_cast<CachedResource*>(resource)->load(this, defaultCachedResourceOptions()); } }