HistoryItem::~HistoryItem() { ASSERT(!m_cachedPage); ASSERT(!m_document); iconDatabase()->releaseIconForPageURL(m_urlString); #if PLATFORM(ANDROID) if (m_bridge) m_bridge->detachHistoryItem(); #endif }
void IconController::continueLoadWithDecision(IconLoadDecision iconLoadDecision) { ASSERT(iconLoadDecision != IconLoadUnknown); // FIXME (<rdar://problem/9168605>) - We should support in-memory-only private browsing icons in asynchronous icon database mode. if (iconDatabase().supportsAsynchronousMode() && m_frame->page()->settings()->privateBrowsingEnabled()) return; if (iconLoadDecision == IconLoadNo) { KURL iconURL(url()); String urlString(iconURL.string()); if (urlString.isEmpty()) return; LOG(IconDatabase, "IconController::startLoader() - Told not to load this icon, committing iconURL %s to database for pageURL mapping", urlString.ascii().data()); commitToDatabase(iconURL); if (iconDatabase().supportsAsynchronousMode()) { m_frame->loader()->documentLoader()->getIconDataForIconURL(urlString); return; } // We were told not to load this icon - that means this icon is already known by the database // If the icon data hasn't been read in from disk yet, kick off the read of the icon from the database to make sure someone // has done it. This is after registering for the notification so the WebView can call the appropriate delegate method. // Otherwise if the icon data *is* available, notify the delegate if (!iconDatabase().synchronousIconDataKnownForIconURL(urlString)) { LOG(IconDatabase, "Told not to load icon %s but icon data is not yet available - registering for notification and requesting load from disk", urlString.ascii().data()); m_frame->loader()->client()->registerForIconNotification(); iconDatabase().synchronousIconForPageURL(m_frame->document()->url().string(), IntSize(0, 0)); iconDatabase().synchronousIconForPageURL(m_frame->loader()->initialRequest().url().string(), IntSize(0, 0)); } else m_frame->loader()->client()->dispatchDidReceiveIcon(); return; } if (!m_iconLoader) m_iconLoader = IconLoader::create(m_frame); m_iconLoader->startLoading(); }
HistoryItem::HistoryItem(const String& urlString, const String& title, double time) : m_urlString(urlString) , m_originalURLString(urlString) , m_title(title) , m_lastVisitedTime(time) , m_isInPageCache(false) , m_isTargetItem(false) , m_visitCount(0) { iconDatabase()->retainIconForPageURL(m_urlString); }
HistoryItem::HistoryItem(const String& urlString, const String& title, double time) : m_urlString(urlString) , m_originalURLString(urlString) , m_title(title) , m_lastVisitedTime(time) , m_lastVisitWasHTTPNonGet(false) , m_lastVisitWasFailure(false) , m_isTargetItem(false) , m_visitCount(0) , m_documentSequenceNumber(generateDocumentSequenceNumber()) { iconDatabase()->retainIconForPageURL(m_urlString); }
HistoryItem::HistoryItem(const String& urlString, const String& title) : m_urlString(urlString) , m_originalURLString(urlString) , m_title(title) , m_pageScaleFactor(0) , m_lastVisitWasFailure(false) , m_isTargetItem(false) , m_itemSequenceNumber(generateSequenceNumber()) , m_documentSequenceNumber(generateSequenceNumber()) , m_pruningReason(PruningReason::None) { iconDatabase().retainIconForPageURL(m_urlString); }
HistoryItem::HistoryItem(const String& urlString, const String& title, const String& alternateTitle, double time) : m_urlString(urlString) , m_originalURLString(urlString) , m_title(title) , m_displayTitle(alternateTitle) , m_lastVisitedTime(time) , m_lastVisitWasHTTPNonGet(false) , m_lastVisitWasFailure(false) , m_isTargetItem(false) , m_visitCount(0) { iconDatabase()->retainIconForPageURL(m_urlString); }
HistoryItem::HistoryItem(const KURL& url, const String& target, const String& parent, const String& title) : m_urlString(url.string()) , m_originalURLString(url.string()) , m_target(target) , m_parent(parent) , m_title(title) , m_lastVisitedTime(0) , m_isInPageCache(false) , m_isTargetItem(false) , m_visitCount(0) { iconDatabase()->retainIconForPageURL(m_urlString); }
HistoryItem::HistoryItem(const KURL& url, const String& target, const String& parent, const String& title) : m_urlString(url.string()) , m_originalURLString(url.string()) , m_target(target) , m_parent(parent) , m_title(title) , m_lastVisitedTime(0) , m_lastVisitWasHTTPNonGet(false) , m_lastVisitWasFailure(false) , m_isTargetItem(false) , m_visitCount(0) , m_itemSequenceNumber(generateSequenceNumber()) , m_documentSequenceNumber(generateSequenceNumber()) { iconDatabase()->retainIconForPageURL(m_urlString); }
HistoryItem::HistoryItem(const String& urlString, const String& title, const String& alternateTitle, double time) : m_urlString(urlString) , m_originalURLString(urlString) , m_title(title) , m_displayTitle(alternateTitle) , m_lastVisitedTime(time) , m_lastVisitWasHTTPNonGet(false) , m_pageScaleFactor(0) , m_lastVisitWasFailure(false) , m_isTargetItem(false) , m_visitCount(0) , m_itemSequenceNumber(generateSequenceNumber()) , m_documentSequenceNumber(generateSequenceNumber()) , m_next(0) , m_prev(0) { iconDatabase().retainIconForPageURL(m_urlString); }
void IconLoader::finishLoading(const KURL& iconURL, PassRefPtr<SharedBuffer> data) { // When an icon load results in a 404 we commit it to the database here and clear the loading state. // But the SubresourceLoader continues pulling in data in the background for the 404 page if the server sends one. // Once that data finishes loading or if the load is cancelled while that data is being read, finishLoading ends up being called a second time. // We need to change SubresourceLoader to have a mode where it will stop itself after receiving a 404 so this won't happen - // in the meantime, we'll only commit this data to the IconDatabase if it's the first time ::finishLoading() is called // <rdar://problem/5463392> tracks that enhancement if (!iconURL.isEmpty() && m_loadIsInProgress) { iconDatabase()->setIconDataForIconURL(data, iconURL.string()); LOG(IconDatabase, "IconLoader::finishLoading() - Committing iconURL %s to database", iconURL.string().ascii().data()); m_frame->loader()->commitIconURLToIconDatabase(iconURL); m_frame->loader()->client()->dispatchDidReceiveIcon(); } clearLoadingState(); }
HistoryItem::HistoryItem(const String& urlString, const String& title, const String& alternateTitle) : m_urlString(urlString) , m_originalURLString(urlString) , m_title(title) , m_displayTitle(alternateTitle) , m_pageScaleFactor(0) , m_lastVisitWasFailure(false) , m_isTargetItem(false) , m_itemSequenceNumber(generateSequenceNumber()) , m_documentSequenceNumber(generateSequenceNumber()) , m_pruningReason(PruningReason::None) #if PLATFORM(IOS) , m_scale(0) , m_scaleIsInitial(false) , m_bookmarkID(0) #endif { iconDatabase().retainIconForPageURL(m_urlString); }
void IconLoader::notifyFinished(CachedResource* resource) { ASSERT(resource == m_resource); // If we got a status code indicating an invalid response, then lets // ignore the data and not try to decode the error page as an icon. RefPtr<ResourceBuffer> data = resource->resourceBuffer(); int status = resource->response().httpStatusCode(); if (status && (status < 200 || status > 299)) data = 0; LOG(IconDatabase, "IconLoader::finishLoading() - Committing iconURL %s to database", resource->url().string().ascii().data()); m_frame->loader()->icon()->commitToDatabase(resource->url()); // Setting the icon data only after committing to the database ensures that the data is // kept in memory (so it does not have to be read from the database asynchronously), since // there is a page URL referencing it. iconDatabase().setIconDataForIconURL(data ? data->sharedBuffer() : 0, resource->url().string()); m_frame->loader()->client()->dispatchDidReceiveIcon(); stopLoading(); }
HistoryItem::HistoryItem(const URL& url, const String& target, const String& parent, const String& title) : m_urlString(url.string()) , m_originalURLString(url.string()) , m_target(target) , m_parent(parent) , m_title(title) , m_pageScaleFactor(0) , m_lastVisitWasFailure(false) , m_isTargetItem(false) , m_itemSequenceNumber(generateSequenceNumber()) , m_documentSequenceNumber(generateSequenceNumber()) , m_next(0) , m_prev(0) #if PLATFORM(IOS) , m_scale(0) , m_scaleIsInitial(false) , m_bookmarkID(0) #endif { iconDatabase().retainIconForPageURL(m_urlString); }
HistoryItem::HistoryItem(const String& urlString, const String& title, double time) : m_urlString(urlString) , m_originalURLString(urlString) , m_title(title) , m_lastVisitedTime(time) , m_lastVisitWasHTTPNonGet(false) , m_pageScaleFactor(0) , m_lastVisitWasFailure(false) , m_isTargetItem(false) , m_visitCount(0) , m_itemSequenceNumber(generateSequenceNumber()) , m_documentSequenceNumber(generateSequenceNumber()) , m_next(0) , m_prev(0) #if PLATFORM(IOS) , m_scale(0) , m_scaleIsInitial(false) , m_bookmarkID(0) #endif { iconDatabase().retainIconForPageURL(m_urlString); }
HistoryItem::~HistoryItem() { ASSERT(!m_cachedPage); iconDatabase().releaseIconForPageURL(m_urlString); }
HistoryItem::~HistoryItem() { ASSERT(!m_isInPageCache); iconDatabase()->releaseIconForPageURL(m_urlString); }
Image* HistoryItem::icon() const { Image* result = iconDatabase()->iconForPageURL(m_urlString, IntSize(16,16)); return result ? result : iconDatabase()->defaultIcon(IntSize(16,16)); }
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); }
RefPtr<LegacyWebArchive> LegacyWebArchive::create(const String& markupString, Frame& frame, const Vector<Node*>& nodes, std::function<bool (Frame&)> frameFilter) { 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()); if (!mainResource) return nullptr; Vector<RefPtr<LegacyWebArchive>> subframeArchives; Vector<RefPtr<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 ((is<HTMLFrameElementBase>(node) || is<HTMLObjectElement>(node)) && (childFrame = downcast<HTMLFrameOwnerElement>(node).contentFrame())) { if (frameFilter && !frameFilter(*childFrame)) continue; if (RefPtr<LegacyWebArchive> subframeArchive = create(*childFrame->document(), frameFilter)) subframeArchives.append(WTFMove(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(); for (const auto& subresourceURL : subresourceURLs) { if (uniqueSubresources.contains(subresourceURL)) continue; uniqueSubresources.add(subresourceURL); if (RefPtr<ArchiveResource> resource = documentLoader->subresource(subresourceURL)) { subresources.append(WTFMove(resource)); continue; } ResourceRequest request(subresourceURL); #if ENABLE(CACHE_PARTITIONING) request.setDomainForCachePartition(frame.document()->topOrigin()->domainForCachePartition()); #endif CachedResource* cachedResource = MemoryCache::singleton().resourceForRequest(request, frame.page()->sessionID()); if (cachedResource) { if (RefPtr<ArchiveResource> resource = ArchiveResource::create(cachedResource->resourceBuffer(), subresourceURL, cachedResource->response())) { subresources.append(WTFMove(resource)); 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(WTFMove(mainResource), WTFMove(subresources), WTFMove(subframeArchives)); }
void IconController::commitToDatabase(const KURL& icon) { LOG(IconDatabase, "Committing iconURL %s to database for pageURLs %s and %s", icon.string().ascii().data(), m_frame->document()->url().string().ascii().data(), m_frame->loader()->initialRequest().url().string().ascii().data()); iconDatabase().setIconURLForPageURL(icon.string(), m_frame->document()->url().string()); iconDatabase().setIconURLForPageURL(icon.string(), m_frame->loader()->initialRequest().url().string()); }
void DocumentLoader::iconLoadDecisionAvailable() { if (m_frame) m_frame->loader()->icon()->loadDecisionReceived(iconDatabase().synchronousLoadDecisionForIconURL(frameLoader()->icon()->url(), this)); }
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); }