From db1db7b701288f4c5ca4545f524370f2c7b47e4e Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Wed, 13 Dec 2017 19:46:03 -0800 Subject: [PATCH] =?UTF-8?q?Cache=20parsed=20metadata=20when=20finding=20a?= =?UTF-8?q?=20home=20page=E2=80=99s=20favicon=20URL.=20Also:=20do=20the=20?= =?UTF-8?q?parsing=20in=20the=20background,=20for=20performance=20reasons.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Evergreen/Favicons/FaviconURLFinder.swift | 33 ++++++++++++++++++----- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/Evergreen/Favicons/FaviconURLFinder.swift b/Evergreen/Favicons/FaviconURLFinder.swift index 07cae4c8a..fe0324e89 100644 --- a/Evergreen/Favicons/FaviconURLFinder.swift +++ b/Evergreen/Favicons/FaviconURLFinder.swift @@ -9,11 +9,15 @@ import Foundation import RSParser import RSWeb +import RSCore // The favicon URL may be specified in the head section of the home page. struct FaviconURLFinder { + static var metadataCache = [String: RSHTMLMetadata]() + static let serialDispatchQueue = DispatchQueue(label: "FaviconURLFinder") + static func findFaviconURL(_ homePageURL: String, _ callback: @escaping (String?) -> Void) { guard let url = URL(string: homePageURL) else { @@ -36,16 +40,33 @@ struct FaviconURLFinder { // will be made absolute correctly. let urlToUse = response.url?.absoluteString ?? homePageURL - let link = faviconURL(urlToUse, data) - callback(link) + faviconURL(urlToUse, data, callback) } } - static private func faviconURL(_ url: String, _ webPageData: Data) -> String? { + static private func faviconURL(_ url: String, _ webPageData: Data, _ callback: @escaping (String?) -> Void) { - let parserData = ParserData(url: url, data: webPageData) - let htmlMetadata = RSHTMLMetadataParser.htmlMetadata(with: parserData) - return htmlMetadata.faviconLink + serialDispatchQueue.async { + + let md5String = (webPageData as NSData).rs_md5HashString() + if let md5String = md5String, let cachedMetadata = metadataCache[md5String] { + let cachedURL = cachedMetadata.faviconLink + DispatchQueue.main.async { + callback(cachedURL) + } + return + } + + let parserData = ParserData(url: url, data: webPageData) + let htmlMetadata = RSHTMLMetadataParser.htmlMetadata(with: parserData) + if let md5String = md5String { + metadataCache[md5String] = htmlMetadata + } + let url = htmlMetadata.faviconLink + DispatchQueue.main.async { + callback(url) + } + } } }