Skip to content
This repository has been archived by the owner on May 10, 2024. It is now read-only.

Fix#2907: Clearing Browsing History should clear Tab History as well #3089

Merged
merged 7 commits into from
Jan 7, 2021
Merged
39 changes: 35 additions & 4 deletions Client/Frontend/Browser/Tab.swift
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,31 @@ 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)

/*
* Remove all items selector is used on WKWebView backForwardList because backForwardList list is only exposed with a getter
* 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] = ["_r", "emoveA", "llIt", "ems"]

let method = argument.compactMap { $0 as? String }.joined()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Looks good. This MIGHT not work if the optimizer is smart. If it is, this will get optimized back into a single string _clear and then get flagged by the automatic review for private methods :D
Typically I base-64 encode the string and then decode it at runtime. But for now, leave it and let's see. Just adding a comment in case it does get rekt.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I added extra obfuscation which includes base-64 encode and unicode encoding but we decided it is unnecessary.
But like you said let's see, we can put it back.

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,
Expand All @@ -265,6 +290,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
Expand All @@ -275,19 +301,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 {
Expand Down
6 changes: 6 additions & 0 deletions Client/Frontend/Browser/TabManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() })
Expand Down Expand Up @@ -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(())
})
Expand Down
12 changes: 12 additions & 0 deletions Data/models/TabMO.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down