diff --git a/Shared/Favicons/FaviconDownloader.swift b/Shared/Favicons/FaviconDownloader.swift index 447012cd6..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 @@ -60,6 +61,8 @@ final class FaviconDownloader { loadHomePageToFaviconURLCache() loadHomePageURLsWithNoFaviconURLCache() + FaviconURLFinder.ignoredTypes = [kUTTypeScalableVectorGraphics as String] + NotificationCenter.default.addObserver(self, selector: #selector(didLoadFavicon(_:)), name: .DidLoadFavicon, object: nil) } @@ -208,7 +211,7 @@ private extension FaviconDownloader { return } - FaviconURLFinder.findFaviconURLs(homePageURL) { (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 654dd1f3b..0f80b44d8 100644 --- a/Shared/Favicons/FaviconURLFinder.swift +++ b/Shared/Favicons/FaviconURLFinder.swift @@ -7,21 +7,63 @@ // import Foundation +import CoreServices import RSParser // The favicon URLs may be specified in the head section of the home page. struct FaviconURLFinder { - static func findFaviconURLs(_ homePageURL: String, _ completion: @escaping ([String]?) -> Void) { + 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 { + return + } + + 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]) + } + } + } + } + + /// 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 - completion(htmlMetadata?.faviconLinks) + 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: favicon.urlString), ignoredExtensions.contains(url.pathExtension) { + return false + } + } + + return true + }).map { $0.urlString } + + completion(faviconURLs) } } } 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