/* 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/. */ import Foundation import Shared import WebKit import Deferred import SDWebImage import CoreSpotlight private let log = Logger.browserLogger // Removed Clearables as part of Bug 1226654, but keeping the string around. private let removedSavedLoginsLabel = NSLocalizedString("Saved Logins", tableName: "ClearPrivateData", comment: "Settings item for clearing passwords and login data") // A base protocol for something that can be cleared. protocol Clearable { func clear() -> Success var label: String { get } } class ClearableError: MaybeErrorType { fileprivate let msg: String init(msg: String) { self.msg = msg } var description: String { return msg } } // Clears our browsing history, including favicons and thumbnails. class HistoryClearable: Clearable { let profile: Profile init(profile: Profile) { self.profile = profile } var label: String { return NSLocalizedString("Browsing History", tableName: "ClearPrivateData", comment: "Settings item for clearing browsing history") } func clear() -> Success { return profile.history.clearHistory().bindQueue(.main) { success in SDImageCache.shared().clearDisk() SDImageCache.shared().clearMemory() self.profile.recentlyClosedTabs.clearTabs() CSSearchableIndex.default().deleteAllSearchableItems() NotificationCenter.default.post(name: NotificationPrivateDataClearedHistory, object: nil) log.debug("HistoryClearable succeeded: \(success).") return Deferred(value: success) } } } struct ClearableErrorType: MaybeErrorType { let err: Error init(err: Error) { self.err = err } var description: String { return "Couldn't clear: \(err)." } } // Clear the web cache. Note, this has to close all open tabs in order to ensure the data // cached in them isn't flushed to disk. class CacheClearable: Clearable { let tabManager: TabManager init(tabManager: TabManager) { self.tabManager = tabManager } var label: String { return NSLocalizedString("Cache", tableName: "ClearPrivateData", comment: "Settings item for clearing the cache") } func clear() -> Success { let dataTypes = Set([WKWebsiteDataTypeDiskCache, WKWebsiteDataTypeMemoryCache]) WKWebsiteDataStore.default().removeData(ofTypes: dataTypes, modifiedSince: Date.distantPast, completionHandler: {}) log.debug("CacheClearable succeeded.") return succeed() } } private func deleteLibraryFolderContents(_ folder: String) throws { let manager = FileManager.default let library = manager.urls(for: FileManager.SearchPathDirectory.libraryDirectory, in: .userDomainMask)[0] let dir = library.appendingPathComponent(folder) let contents = try manager.contentsOfDirectory(atPath: dir.path) for content in contents { do { try manager.removeItem(at: dir.appendingPathComponent(content)) } catch where ((error as NSError).userInfo[NSUnderlyingErrorKey] as? NSError)?.code == Int(EPERM) { // "Not permitted". We ignore this. log.debug("Couldn't delete some library contents.") } } } private func deleteLibraryFolder(_ folder: String) throws { let manager = FileManager.default let library = manager.urls(for: FileManager.SearchPathDirectory.libraryDirectory, in: .userDomainMask)[0] let dir = library.appendingPathComponent(folder) try manager.removeItem(at: dir) } // Removes all app cache storage. class SiteDataClearable: Clearable { let tabManager: TabManager init(tabManager: TabManager) { self.tabManager = tabManager } var label: String { return NSLocalizedString("Offline Website Data", tableName: "ClearPrivateData", comment: "Settings item for clearing website data") } func clear() -> Success { let dataTypes = Set([WKWebsiteDataTypeOfflineWebApplicationCache]) WKWebsiteDataStore.default().removeData(ofTypes: dataTypes, modifiedSince: Date.distantPast, completionHandler: {}) log.debug("SiteDataClearable succeeded.") return succeed() } } // Remove all cookies stored by the site. This includes localStorage, sessionStorage, and WebSQL/IndexedDB. class CookiesClearable: Clearable { let tabManager: TabManager init(tabManager: TabManager) { self.tabManager = tabManager } var label: String { return NSLocalizedString("Cookies", tableName: "ClearPrivateData", comment: "Settings item for clearing cookies") } func clear() -> Success { let dataTypes = Set([WKWebsiteDataTypeCookies, WKWebsiteDataTypeLocalStorage, WKWebsiteDataTypeSessionStorage, WKWebsiteDataTypeWebSQLDatabases, WKWebsiteDataTypeIndexedDBDatabases]) WKWebsiteDataStore.default().removeData(ofTypes: dataTypes, modifiedSince: Date.distantPast, completionHandler: {}) log.debug("CookiesClearable succeeded.") return succeed() } }