From f65bf63bb1b555ae90485377410faad314eab7e3 Mon Sep 17 00:00:00 2001 From: Nate Weaver Date: Fri, 31 Jan 2020 15:59:16 -0600 Subject: [PATCH 1/5] Add the ability to ignore types to FaviconURLFinder, and ignore SVG favicons --- Shared/Favicons/FaviconDownloader.swift | 4 ++- Shared/Favicons/FaviconURLFinder.swift | 39 +++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/Shared/Favicons/FaviconDownloader.swift b/Shared/Favicons/FaviconDownloader.swift index 447012cd6..94b562e85 100644 --- a/Shared/Favicons/FaviconDownloader.swift +++ b/Shared/Favicons/FaviconDownloader.swift @@ -208,7 +208,9 @@ private extension FaviconDownloader { return } - FaviconURLFinder.findFaviconURLs(homePageURL) { (faviconURLs) in + let ignoredTypes = [kUTTypeScalableVectorGraphics as String] + + FaviconURLFinder.findFaviconURLs(with: homePageURL, ignoredTypes: ignoredTypes) { (faviconURLs) in var defaultFaviconURL: String? = nil if let scheme = url.scheme, let host = url.host { diff --git a/Shared/Favicons/FaviconURLFinder.swift b/Shared/Favicons/FaviconURLFinder.swift index 654dd1f3b..fc05dd66c 100644 --- a/Shared/Favicons/FaviconURLFinder.swift +++ b/Shared/Favicons/FaviconURLFinder.swift @@ -13,15 +13,50 @@ import RSParser struct FaviconURLFinder { - static func findFaviconURLs(_ homePageURL: String, _ completion: @escaping ([String]?) -> Void) { + /// Finds favicon URLs in a web page. + /// - Parameters: + /// - homePageURL: The page to search. + /// - ignoredTypes: An array of uniform type identifiers to ignore. + /// - completion: A closure called when the links have been found. + /// - urls: An array of favicon URLs as strings. + static func findFaviconURLs(with homePageURL: String, ignoredTypes ignoredTypes: [String]? = nil, _ completion: @escaping (_ urls:[String]?) -> Void) { guard let _ = URL(string: homePageURL) else { completion(nil) return } + var ignoredMimeTypes = [String]() + var ignoredExtensions = [String]() + + if let ignoredTypes = ignoredTypes { + for type in ignoredTypes { + if let mimeTypes = UTTypeCopyAllTagsWithClass(type as CFString, kUTTagClassMIMEType)?.takeRetainedValue() { + ignoredMimeTypes.append(contentsOf: mimeTypes as! [String]) + } + if let extensions = UTTypeCopyAllTagsWithClass(type as CFString, kUTTagClassFilenameExtension)?.takeRetainedValue() { + ignoredExtensions.append(contentsOf: extensions as! [String]) + } + } + } + + // If the favicon has an explicit type, check that for an ignored type; otherwise, check the file extension. HTMLMetadataDownloader.downloadMetadata(for: homePageURL) { (htmlMetadata) in - completion(htmlMetadata?.faviconLinks) + let faviconURLs = htmlMetadata?.faviconLinks.filter({ (faviconLink) -> Bool in + if faviconLink.type != nil { + if ignoredMimeTypes.contains(faviconLink.type) { + return false + } + } else { + if let url = URL(string: faviconLink.urlString!), ignoredExtensions.contains(url.pathExtension) { + return false + } + } + + return true + }).map { $0.urlString! } + + completion(faviconURLs) } } } From 101e1402332852dc1f1d4be7368413c7c9937911 Mon Sep 17 00:00:00 2001 From: Nate Weaver Date: Fri, 31 Jan 2020 16:09:01 -0600 Subject: [PATCH 2/5] Make ignoredTypes a static property to avoid redundant lookups --- Shared/Favicons/FaviconDownloader.swift | 6 ++--- Shared/Favicons/FaviconURLFinder.swift | 35 ++++++++++++++----------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/Shared/Favicons/FaviconDownloader.swift b/Shared/Favicons/FaviconDownloader.swift index 94b562e85..655e20989 100644 --- a/Shared/Favicons/FaviconDownloader.swift +++ b/Shared/Favicons/FaviconDownloader.swift @@ -60,6 +60,8 @@ final class FaviconDownloader { loadHomePageToFaviconURLCache() loadHomePageURLsWithNoFaviconURLCache() + FaviconURLFinder.ignoredTypes = [kUTTypeScalableVectorGraphics as String] + NotificationCenter.default.addObserver(self, selector: #selector(didLoadFavicon(_:)), name: .DidLoadFavicon, object: nil) } @@ -208,9 +210,7 @@ private extension FaviconDownloader { return } - let ignoredTypes = [kUTTypeScalableVectorGraphics as String] - - FaviconURLFinder.findFaviconURLs(with: homePageURL, ignoredTypes: ignoredTypes) { (faviconURLs) in + FaviconURLFinder.findFaviconURLs(with: homePageURL) { (faviconURLs) in var defaultFaviconURL: String? = nil if let scheme = url.scheme, let host = url.host { diff --git a/Shared/Favicons/FaviconURLFinder.swift b/Shared/Favicons/FaviconURLFinder.swift index fc05dd66c..21edc1ab2 100644 --- a/Shared/Favicons/FaviconURLFinder.swift +++ b/Shared/Favicons/FaviconURLFinder.swift @@ -13,23 +13,15 @@ import RSParser struct FaviconURLFinder { - /// Finds favicon URLs in a web page. - /// - Parameters: - /// - homePageURL: The page to search. - /// - ignoredTypes: An array of uniform type identifiers to ignore. - /// - completion: A closure called when the links have been found. - /// - urls: An array of favicon URLs as strings. - static func findFaviconURLs(with homePageURL: String, ignoredTypes ignoredTypes: [String]? = nil, _ completion: @escaping (_ urls:[String]?) -> Void) { + private static var ignoredMimeTypes = [String]() + private static var ignoredExtensions = [String]() - guard let _ = URL(string: homePageURL) else { - completion(nil) - return - } + static var ignoredTypes: [String]? { + didSet { + guard let ignoredTypes = ignoredTypes else { + return + } - var ignoredMimeTypes = [String]() - var ignoredExtensions = [String]() - - if let ignoredTypes = ignoredTypes { for type in ignoredTypes { if let mimeTypes = UTTypeCopyAllTagsWithClass(type as CFString, kUTTagClassMIMEType)?.takeRetainedValue() { ignoredMimeTypes.append(contentsOf: mimeTypes as! [String]) @@ -39,6 +31,19 @@ struct FaviconURLFinder { } } } + } + + /// Finds favicon URLs in a web page. + /// - Parameters: + /// - homePageURL: The page to search. + /// - completion: A closure called when the links have been found. + /// - urls: An array of favicon URLs as strings. + static func findFaviconURLs(with homePageURL: String, _ completion: @escaping (_ urls:[String]?) -> Void) { + + guard let _ = URL(string: homePageURL) else { + completion(nil) + return + } // If the favicon has an explicit type, check that for an ignored type; otherwise, check the file extension. HTMLMetadataDownloader.downloadMetadata(for: homePageURL) { (htmlMetadata) in From e9a37642704d16757ee40e013de5efed9b519df9 Mon Sep 17 00:00:00 2001 From: Nate Weaver Date: Fri, 31 Jan 2020 16:33:35 -0600 Subject: [PATCH 3/5] Documentation comment --- Shared/Favicons/FaviconURLFinder.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Shared/Favicons/FaviconURLFinder.swift b/Shared/Favicons/FaviconURLFinder.swift index 21edc1ab2..b1183f930 100644 --- a/Shared/Favicons/FaviconURLFinder.swift +++ b/Shared/Favicons/FaviconURLFinder.swift @@ -16,6 +16,7 @@ struct FaviconURLFinder { private static var ignoredMimeTypes = [String]() private static var ignoredExtensions = [String]() + /// Uniform types to ignore when finding favicon URLs. static var ignoredTypes: [String]? { didSet { guard let ignoredTypes = ignoredTypes else { From 830db84c567cb1a4b3f1db9c130b75c41c8b5d6e Mon Sep 17 00:00:00 2001 From: Nate Weaver Date: Sat, 1 Feb 2020 01:09:36 -0600 Subject: [PATCH 4/5] Explicitly import CoreServices For UTType stuff; iOS doesn't implicitly import it. --- Shared/Favicons/FaviconDownloader.swift | 1 + Shared/Favicons/FaviconURLFinder.swift | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Shared/Favicons/FaviconDownloader.swift b/Shared/Favicons/FaviconDownloader.swift index 655e20989..aeb42f960 100644 --- a/Shared/Favicons/FaviconDownloader.swift +++ b/Shared/Favicons/FaviconDownloader.swift @@ -7,6 +7,7 @@ // import Foundation +import CoreServices import Articles import Account import RSCore diff --git a/Shared/Favicons/FaviconURLFinder.swift b/Shared/Favicons/FaviconURLFinder.swift index b1183f930..0f80b44d8 100644 --- a/Shared/Favicons/FaviconURLFinder.swift +++ b/Shared/Favicons/FaviconURLFinder.swift @@ -7,6 +7,7 @@ // import Foundation +import CoreServices import RSParser // The favicon URLs may be specified in the head section of the home page. @@ -48,19 +49,19 @@ struct FaviconURLFinder { // If the favicon has an explicit type, check that for an ignored type; otherwise, check the file extension. HTMLMetadataDownloader.downloadMetadata(for: homePageURL) { (htmlMetadata) in - let faviconURLs = htmlMetadata?.faviconLinks.filter({ (faviconLink) -> Bool in - if faviconLink.type != nil { - if ignoredMimeTypes.contains(faviconLink.type) { + let faviconURLs = htmlMetadata?.favicons.filter({ (favicon) -> Bool in + if let type = favicon.type { + if ignoredMimeTypes.contains(type) { return false } } else { - if let url = URL(string: faviconLink.urlString!), ignoredExtensions.contains(url.pathExtension) { + if let url = URL(string: favicon.urlString), ignoredExtensions.contains(url.pathExtension) { return false } } return true - }).map { $0.urlString! } + }).map { $0.urlString } completion(faviconURLs) } From ce73922a25d58b49fa216a036e70ee8374b513bc Mon Sep 17 00:00:00 2001 From: Nate Weaver Date: Sat, 1 Feb 2020 18:21:01 -0600 Subject: [PATCH 5/5] Update RSParser --- submodules/RSParser | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submodules/RSParser b/submodules/RSParser index 50072e628..80952dabd 160000 --- a/submodules/RSParser +++ b/submodules/RSParser @@ -1 +1 @@ -Subproject commit 50072e62800b98c3f9f9cd5b1aae6d5b12c3a58c +Subproject commit 80952dabda6b49e8fa72d8f4cd703fe09fb56564