Skip to content

Commit

Permalink
Add favicon to tabs and bookmarks
Browse files Browse the repository at this point in the history
  • Loading branch information
subsymbolic authored Mar 23, 2017
1 parent 43ab345 commit 21b80bd
Show file tree
Hide file tree
Showing 25 changed files with 600 additions and 264 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@
path = Submodule/Toast-Swift
url = https://github.com/TheInfiniteKind/Toast-Swift
branch = feature/swift-3.0
[submodule "Submodule/Kingfisher"]
path = Submodule/Kingfisher
url = https://github.com/TheInfiniteKind/Kingfisher
2 changes: 2 additions & 0 deletions Core/AppUrls.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public struct AppUrls {

public static let base = "duckduckgo.com"

public static let favicon = "https://duckduckgo.com/favicon.ico"

public static let home = "https://www.duckduckgo.com/?ko=-1&kl=wt-wt"

public static let autocomplete = "https://duckduckgo.com/ac/"
Expand Down
12 changes: 7 additions & 5 deletions Core/JavascriptLoader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,17 @@
import Foundation
import WebKit

public enum ScriptFile: String {
case documentExtension
}

public class JavascriptLoader {

public func load(_ scriptFile: ScriptFile, withController controller: WKUserContentController) {
public enum Script: String {
case document
case favicon
}

public func load(_ script: Script, withController controller: WKUserContentController) {
let bundle = Bundle(for: JavascriptLoader.self)
let path = bundle.path(forResource: scriptFile.rawValue, ofType: "js")!
let path = bundle.path(forResource: script.rawValue, ofType: "js")!
let scriptString = try! String(contentsOfFile: path)
let script = WKUserScript(source: scriptString, injectionTime: .atDocumentStart, forMainFrameOnly: true)
controller.addUserScript(script)
Expand Down
15 changes: 11 additions & 4 deletions Core/Link.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,34 @@ public class Link: NSObject, NSCoding {

public let title: String
public let url: URL
public let favicon: URL?

private struct NSCodingKeys {
static let title = "title"
static let url = "url"
static let favicon = "favicon"
}

public required init(title: String, url: URL) {
public required init(title: String, url: URL, favicon: URL? = nil) {
self.title = title
self.url = url
self.favicon = favicon
}

public convenience required init?(coder aDecoder: NSCoder) {
guard let title = aDecoder.decodeObject(forKey: NSCodingKeys.title) as? String,
let url = aDecoder.decodeObject(forKey: NSCodingKeys.url) as? URL else {
return nil
}
self.init(title: title, url: url)
let favicon = aDecoder.decodeObject(forKey: NSCodingKeys.favicon) as? URL
self.init(title: title, url: url, favicon: favicon)
}

public func encode(with aCoder: NSCoder) {
aCoder.encode(title, forKey: (NSCodingKeys.title))
aCoder.encode(url, forKey: (NSCodingKeys.url))
aCoder.encode(title, forKey: NSCodingKeys.title)
aCoder.encode(url, forKey: NSCodingKeys.url)
if let favicon = favicon {
aCoder.encode(favicon, forKey: NSCodingKeys.favicon)
}
}
}
43 changes: 30 additions & 13 deletions Core/WKWebViewExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,40 @@ extension WKWebView {
return webView
}

public func loadScripts() {
let javascriptLoader = JavascriptLoader()
javascriptLoader.load(.documentExtension, withController: configuration.userContentController)
}

public func clearCache(completionHandler: @escaping () -> Swift.Void) {
let allData = WKWebsiteDataStore.allWebsiteDataTypes()
let distantPast = Date.distantPast
let dataStore = configuration.websiteDataStore
dataStore.removeData(ofTypes: allData, modifiedSince: distantPast, completionHandler: completionHandler)
}


public func loadScripts() {
load(scripts: [.document, .favicon])
}

private func load(scripts: [JavascriptLoader.Script]) {
let javascriptLoader = JavascriptLoader()
for script in scripts {
javascriptLoader.load(script, withController: configuration.userContentController)
}
}

public func getUrlAtPoint(x: Int, y: Int, completion: @escaping (URL?) -> Swift.Void) {
let javascript = "duckduckgoDocument.getHrefFromPoint(\(x), \(y))"
evaluateJavaScript(javascript) { (result, error) in
if let text = result as? String {
let url = URL(string: text)
completion(url)
} else {
completion(nil)
}
}
}

public func getUrlAtPointSynchronously(x: Int, y: Int) -> URL? {
var complete = false
var url: URL?
let javascript = "getHrefFromPoint(\(x), \(y))"
let javascript = "duckduckgoDocument.getHrefFromPoint(\(x), \(y))"
evaluateJavaScript(javascript) { (result, error) in
if let text = result as? String {
url = URL(string: text)
Expand All @@ -56,13 +74,12 @@ extension WKWebView {
return url
}

public func getUrlAtPoint(x: Int, y: Int, completion: @escaping (URL?) -> Swift.Void) {
let javascript = "getHrefFromPoint(\(x), \(y))"
public func getFavicon(completion: @escaping (URL?) -> Swift.Void) {
let javascript = "duckduckgoFavicon.getFavicon()"
evaluateJavaScript(javascript) { (result, error) in
if let text = result as? String {
let url = URL(string: text)
completion(url)
}
guard let urlString = result as? String else { completion(nil); return }
guard let url = URL(string: urlString) else { completion(nil); return }
completion(url)
}
}
}
6 changes: 6 additions & 0 deletions Core/WebViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ open class WebViewController: UIViewController, WKNavigationDelegate {
return webView.url
}

public var favicon: URL?

public var link: Link? {
if let url = webView.url, let title = name {
return Link(title: title, url: url)
Expand Down Expand Up @@ -118,12 +120,16 @@ open class WebViewController: UIViewController, WKNavigationDelegate {
}

public func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
favicon = nil
showProgressIndicator()
webEventsDelegate?.webpageDidStartLoading()
}

public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
hideProgressIndicator()
webView.getFavicon(completion: { [weak self] (favicon) in
self?.favicon = favicon
})
webEventsDelegate?.webpageDidFinishLoading()
}

Expand Down
31 changes: 31 additions & 0 deletions Core/document.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// document.js
// DuckDuckGo
//
// Created by Mia Alexiou on 22/02/2017.
// Copyright © 2017 DuckDuckGo. All rights reserved.
//

var duckduckgoDocument = function () {

getHrefFromPoint = function(x, y) {
var element = document.elementFromPoint(x, y);
while (element && !element.href) {
element = element.parentNode
}
return getHrefFromElement(element)
};

getHrefFromElement = function(element) {
if (element) {
return element.href
}
return null
};

return {
getHrefFromPoint: getHrefFromPoint,
getHrefFromElement: getHrefFromElement
};

}();
22 changes: 0 additions & 22 deletions Core/documentExtension.js

This file was deleted.

47 changes: 47 additions & 0 deletions Core/favicon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/

// Adaptation of https://github.com/mozilla-mobile/firefox-ios/blob/master/Client/Assets/Favicons.js


var duckduckgoFavicon = function() {

var selectors = {
"link[rel~='icon']": 0,
"link[rel='apple-touch-icon']": 1,
"link[rel='apple-touch-icon-precomposed']": 2
};

var cachedFavicon = null;

getFavicon = function() {
if (!cachedFavicon) {
cachedFavicon = findFavicons()[0]
}
return cachedFavicon
};

function findFavicons() {
var favicons = []
for (var selector in selectors) {
var icons = document.head.querySelectorAll(selector);
for (var i = 0; i < icons.length; i++) {
var href = icons[i].href;
favicons.push(href)
}
}
if (favicons.length === 0) {
var href = document.location.origin + "/favicon.ico";
favicons.push(href)
}
return favicons;
};

return {
getFavicon: getFavicon
};

}();
Loading

0 comments on commit 21b80bd

Please sign in to comment.