From aef4874034eaabfa1b6c5677fb8d1a3035aacd42 Mon Sep 17 00:00:00 2001 From: Soner YUKSEL Date: Thu, 7 Jan 2021 17:42:21 -0500 Subject: [PATCH] Fix#2907: Clearing Browsing History should clear Tab History as well (#3089) --- Client/Frontend/Browser/Tab.swift | 40 +++++++++++++++++-- Client/Frontend/Browser/TabManager.swift | 6 +++ ...eShieldsAndPrivacySettingsController.swift | 7 ++++ Data/models/TabMO.swift | 12 ++++++ 4 files changed, 61 insertions(+), 4 deletions(-) diff --git a/Client/Frontend/Browser/Tab.swift b/Client/Frontend/Browser/Tab.swift index c58b5084f21..f7cb1aeb43c 100644 --- a/Client/Frontend/Browser/Tab.swift +++ b/Client/Frontend/Browser/Tab.swift @@ -256,6 +256,32 @@ class Tab: NSObject { contentScriptManager.helpers.removeAll() } + func clearHistory(config: WKWebViewConfiguration) { + guard let webView = webView, + let tabID = id else { + return + } + + // Remove the tab history from saved tabs + TabMO.removeHistory(with: tabID) + + /* + * Clear selector is used on WKWebView backForwardList because backForwardList list is only exposed with a getter + * and this method Removes all items except the current one in the tab list so when another url is added it will add the list properly + * This approach is chosen to achieve removing tab history in the event of removing browser history + * Best way perform this is to clear the backforward list and in our case there is no drawback to clear the list + * And alternative would be to reload webpages which will be costly and also can cause unexpected results + */ + let argument: [Any] = ["_c", "lea", "r"] + + let method = argument.compactMap { $0 as? String }.joined() + let selector: Selector = NSSelectorFromString(method) + + if webView.backForwardList.responds(to: selector) { + webView.backForwardList.performSelector(onMainThread: selector, with: nil, waitUntilDone: true) + } + } + func restore(_ webView: WKWebView, restorationData: SavedTab?) { // Pulls restored session data from a previous SavedTab to load into the Tab. If it's nil, a session restore // has already been triggered via custom URL, so we use the last request to trigger it again; otherwise, @@ -265,6 +291,7 @@ class Tab: NSObject { lastTitle = sessionData.title var updatedURLs = [String]() var previous = "" + for urlString in sessionData.history { guard let url = URL(string: urlString) else { continue } let updatedURL = WebServer.sharedInstance.updateLocalURL(url)!.absoluteString @@ -275,19 +302,24 @@ class Tab: NSObject { previous = current updatedURLs.append(updatedURL) } + let currentPage = sessionData.historyIndex self.sessionData = nil + var jsonDict = [String: AnyObject]() jsonDict[SessionData.Keys.history] = updatedURLs as AnyObject jsonDict[SessionData.Keys.currentPage] = Int(currentPage) as AnyObject - guard let escapedJSON = JSON(jsonDict).rawString()?.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) else { + guard let escapedJSON = JSON(jsonDict).rawString()?.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed), + let restoreURL = URL(string: "\(WebServer.sharedInstance.base)/about/sessionrestore?history=\(escapedJSON)") else { return } - let restoreURL = URL(string: "\(WebServer.sharedInstance.base)/about/sessionrestore?history=\(escapedJSON)") - lastRequest = PrivilegedRequest(url: restoreURL!) as URLRequest - webView.load(lastRequest!) + lastRequest = PrivilegedRequest(url: restoreURL) as URLRequest + + if let request = lastRequest { + webView.load(request) + } } else if let request = lastRequest { webView.load(request) } else { diff --git a/Client/Frontend/Browser/TabManager.swift b/Client/Frontend/Browser/TabManager.swift index 36d53a27f26..06696e747bf 100644 --- a/Client/Frontend/Browser/TabManager.swift +++ b/Client/Frontend/Browser/TabManager.swift @@ -182,6 +182,12 @@ class TabManager: NSObject { }) } + func clearTabHistory() { + allTabs.filter({$0.webView != nil}).forEach({ + $0.clearHistory(config: configuration) + }) + } + func reloadSelectedTab() { let tab = selectedTab _selectedIndex = -1 diff --git a/Client/Frontend/Settings/BraveShieldsAndPrivacySettingsController.swift b/Client/Frontend/Settings/BraveShieldsAndPrivacySettingsController.swift index a5f02994304..f76b65ddfcd 100644 --- a/Client/Frontend/Settings/BraveShieldsAndPrivacySettingsController.swift +++ b/Client/Frontend/Settings/BraveShieldsAndPrivacySettingsController.swift @@ -309,6 +309,8 @@ class BraveShieldsAndPrivacySettingsController: TableViewController { return item is CacheClearable || item is CookiesAndCacheClearable } + let historyCleared = clearables.contains { $0 is HistoryClearable } + if clearAffectsTabs { DispatchQueue.main.async { self.tabManager.allTabs.forEach({ $0.reload() }) @@ -339,6 +341,11 @@ class BraveShieldsAndPrivacySettingsController: TableViewController { if clearAffectsTabs { self.tabManager.allTabs.forEach({ $0.reload() }) } + + if historyCleared { + self.tabManager.clearTabHistory() + } + _toggleFolderAccessForBlockCookies(locked: true) deferred.fill(()) }) diff --git a/Data/models/TabMO.swift b/Data/models/TabMO.swift index fd162e7a492..998e1972c44 100644 --- a/Data/models/TabMO.swift +++ b/Data/models/TabMO.swift @@ -104,6 +104,18 @@ public final class TabMO: NSManagedObject, CRUD { } } + // Deletes the Tab History by removing items except the last one from historysnapshot and setting current index + public class func removeHistory(with tabID: String) { + DataController.perform { context in + guard let tabToUpdate = getInternal(fromId: tabID, context: context) else { return } + + if let lastItem = tabToUpdate.urlHistorySnapshot?.lastObject { + tabToUpdate.urlHistorySnapshot = [lastItem] as NSArray + tabToUpdate.urlHistoryCurrentIndex = 0 + } + } + } + public class func saveScreenshotUUID(_ uuid: UUID?, tabId: String?) { DataController.perform { context in let tabMO = getInternal(fromId: tabId, context: context)