Skip to content

Commit

Permalink
Breakage report improvements (#578)
Browse files Browse the repository at this point in the history
Task/Issue URL: https://app.asana.com/0/1205842942115003/1205692741026215/f
iOS PR: duckduckgo/iOS#2168
macOS PR: duckduckgo/macos-browser#1864
What kind of version bump will this require?: Major (Braking changes in privacy-dashboard)

Description:

The previous implementation of the Report Broken Site page was different between iOS and macOS, with this PR I have updated and aligned the PrivacyDashboardController so the web implementation of the Report Broken Site can be used in both iOS and macOS.
The changes are mostly around delegates and which User script is handled for each platform.

Splitting the delegate into 3 new delegates: PrivacyDashboardNavigationDelegate, PrivacyDashboardReportBrokenSiteDelegate, PrivacyDashboardControllerDelegate
  • Loading branch information
federicocappelli authored Dec 6, 2023
1 parent aa5cd76 commit 074af9d
Show file tree
Hide file tree
Showing 9 changed files with 151 additions and 125 deletions.
4 changes: 2 additions & 2 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/duckduckgo/privacy-dashboard",
"state" : {
"revision" : "daa9708223b4b4318fb6448ca44801dfabcddc6f",
"version" : "3.0.0"
"revision" : "59dedf0f4ff1e9147de0806a54c6043861eb0870",
"version" : "3.1.0"
}
},
{
Expand Down
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ let package = Package(
.package(url: "https://github.com/duckduckgo/TrackerRadarKit", exact: "1.2.1"),
.package(url: "https://github.com/duckduckgo/sync_crypto", exact: "0.2.0"),
.package(url: "https://github.com/gumob/PunycodeSwift.git", exact: "2.1.0"),
.package(url: "https://github.com/duckduckgo/privacy-dashboard", exact: "3.1.0" ),
.package(url: "https://github.com/duckduckgo/content-scope-scripts", exact: "4.52.0"),
.package(url: "https://github.com/duckduckgo/privacy-dashboard", exact: "3.0.0"),
.package(url: "https://github.com/httpswift/swifter.git", exact: "1.5.0"),
.package(url: "https://github.com/duckduckgo/bloom_cpp.git", exact: "3.0.0"),
.package(url: "https://github.com/duckduckgo/wireguard-apple", exact: "1.1.1")
Expand Down
2 changes: 1 addition & 1 deletion Sources/PrivacyDashboard/Model/CookieConsentInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public struct CookieConsentInfo: Encodable {
let optoutFailed: Bool?
let selftestFailed: Bool?
let configurable = true

public init(consentManaged: Bool, cosmetic: Bool?, optoutFailed: Bool?, selftestFailed: Bool?) {
self.consentManaged = consentManaged
self.cosmetic = cosmetic
Expand Down
2 changes: 1 addition & 1 deletion Sources/PrivacyDashboard/Model/ProtectionStatus.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import Foundation

public struct ProtectionStatus: Encodable {

let unprotectedTemporary: Bool
let enabledFeatures: [String]
let allowlisted: Bool
Expand Down
10 changes: 5 additions & 5 deletions Sources/PrivacyDashboard/Model/TrackerInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ public struct TrackerInfo: Encodable {
case requests
case installedSurrogates
}

public private (set) var trackers = Set<DetectedRequest>()
private(set) var thirdPartyRequests = Set<DetectedRequest>()
public private(set) var installedSurrogates = Set<String>()

public init() { }

// MARK: - Collecting detected elements
Expand All @@ -43,12 +43,12 @@ public struct TrackerInfo: Encodable {
public mutating func add(detectedThirdPartyRequest request: DetectedRequest) {
thirdPartyRequests.insert(request)
}

public mutating func addInstalledSurrogateHost(_ host: String, for tracker: DetectedRequest, onPageWithURL url: URL) {
guard tracker.pageUrl == url.absoluteString else { return }
installedSurrogates.insert(host)
}

// MARK: - Helper accessors

public var trackersBlocked: [DetectedRequest] {
Expand All @@ -67,5 +67,5 @@ public struct TrackerInfo: Encodable {
try container.encode(allRequests, forKey: .requests)
try container.encode(installedSurrogates, forKey: .installedSurrogates)
}

}
126 changes: 76 additions & 50 deletions Sources/PrivacyDashboard/PrivacyDashboardController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,58 +26,77 @@ public enum PrivacyDashboardOpenSettingsTarget: String {
case cookiePopupManagement = "cpm"
}

public protocol PrivacyDashboardControllerDelegate: AnyObject {
func privacyDashboardController(_ privacyDashboardController: PrivacyDashboardController,
didChangeProtectionSwitch protectionState: ProtectionState)
func privacyDashboardController(_ privacyDashboardController: PrivacyDashboardController, didRequestOpenUrlInNewTab url: URL)
func privacyDashboardController(_ privacyDashboardController: PrivacyDashboardController,
didRequestOpenSettings target: PrivacyDashboardOpenSettingsTarget)

/// Navigation delegate for the pages provided by the PrivacyDashboardController
public protocol PrivacyDashboardNavigationDelegate: AnyObject {
#if os(iOS)
func privacyDashboardControllerDidTapClose(_ privacyDashboardController: PrivacyDashboardController)
func privacyDashboardControllerDidRequestShowReportBrokenSite(_ privacyDashboardController: PrivacyDashboardController)
#endif

#if os(macOS)

func privacyDashboardController(_ privacyDashboardController: PrivacyDashboardController, didSetHeight height: Int)
func privacyDashboardController(_ privacyDashboardController: PrivacyDashboardController,
}

/// `Report broken site` web page delegate
public protocol PrivacyDashboardReportBrokenSiteDelegate: AnyObject {

func privacyDashboardController(_ privacyDashboardController: PrivacyDashboardController,
didRequestSubmitBrokenSiteReportWithCategory category: String, description: String)
func privacyDashboardController(_ privacyDashboardController: PrivacyDashboardController,
didSetPermission permissionName: String,
to state: PermissionAuthorizationState)
func privacyDashboardController(_ privacyDashboardController: PrivacyDashboardController,
setPermission permissionName: String,
paused: Bool)
#endif
func privacyDashboardController(_ privacyDashboardController: PrivacyDashboardController,
reportBrokenSiteDidChangeProtectionSwitch protectionState: ProtectionState)
}

/// `Privacy Dasboard` web page delegate
public protocol PrivacyDashboardControllerDelegate: AnyObject {

func privacyDashboardController(_ privacyDashboardController: PrivacyDashboardController,
didChangeProtectionSwitch protectionState: ProtectionState)
func privacyDashboardController(_ privacyDashboardController: PrivacyDashboardController,
didRequestOpenUrlInNewTab url: URL)
func privacyDashboardController(_ privacyDashboardController: PrivacyDashboardController,
didRequestOpenSettings target: PrivacyDashboardOpenSettingsTarget)
func privacyDashboardControllerDidRequestShowReportBrokenSite(_ privacyDashboardController: PrivacyDashboardController)

#if os(macOS)
func privacyDashboardController(_ privacyDashboardController: PrivacyDashboardController,
didSetPermission permissionName: String, to state: PermissionAuthorizationState)
func privacyDashboardController(_ privacyDashboardController: PrivacyDashboardController,
setPermission permissionName: String, paused: Bool)
#endif
}

@MainActor
public final class PrivacyDashboardController: NSObject {
/// This controller provides two type of user experiences
/// 1- `Privacy Dashboard` with the possibility to navigate to the `Report broken site` page
/// 2- Direct access to the `Report broken site` page
/// Which flow is used is decided at `setup(...)` time, where if `reportBrokenSiteOnly` is true then the `Report broken site` page is opened directly.
@MainActor public final class PrivacyDashboardController: NSObject {

public weak var delegate: PrivacyDashboardControllerDelegate?
// Delegates
public weak var privacyDashboardDelegate: PrivacyDashboardControllerDelegate?
public weak var privacyDashboardNavigationDelegate: PrivacyDashboardNavigationDelegate?
public weak var privacyDashboardReportBrokenSiteDelegate: PrivacyDashboardReportBrokenSiteDelegate?

@Published public var theme: PrivacyDashboardTheme?
public var preferredLocale: String?
@Published public var allowedPermissions: [AllowedPermission] = []

public private(set) weak var privacyInfo: PrivacyInfo?
private weak var webView: WKWebView?

private weak var webView: WKWebView?
private let privacyDashboardScript = PrivacyDashboardUserScript()
private var cancellables = Set<AnyCancellable>()

public init(privacyInfo: PrivacyInfo?) {
self.privacyInfo = privacyInfo
}

public func setup(for webView: WKWebView) {
/// Configure the webview for showing `Privacy Dasboard` or `Report broken site`
/// - Parameters:
/// - webView: The webview to use
/// - reportBrokenSiteOnly: true = `Report broken site`, false = `Privacy Dasboard`
public func setup(for webView: WKWebView, reportBrokenSiteOnly: Bool) {
self.webView = webView

webView.navigationDelegate = self

setupPrivacyDashboardUserScript()
loadPrivacyDashboardHTML()
loadPrivacyDashboardHTML(reportBrokenSiteOnly: reportBrokenSiteOnly)
}

public func updatePrivacyInfo(_ privacyInfo: PrivacyInfo?) {
Expand Down Expand Up @@ -112,20 +131,25 @@ public final class PrivacyDashboardController: NSObject {
privacyDashboardScript.delegate = self

webView.configuration.userContentController.addUserScript(privacyDashboardScript.makeWKUserScriptSync())

privacyDashboardScript.messageNames.forEach { messageName in
webView.configuration.userContentController.add(privacyDashboardScript, name: messageName)
}
}

private func loadPrivacyDashboardHTML() {
guard let url = Bundle.privacyDashboardURL else { return }
private func loadPrivacyDashboardHTML(reportBrokenSiteOnly: Bool) {
guard var url = Bundle.privacyDashboardURL else { return }

if reportBrokenSiteOnly {
url = url.appendingParameter(name: "screen", value: ProtectionState.EventOriginScreen.breakageForm.rawValue)
}

webView?.loadFileURL(url, allowingReadAccessTo: url.deletingLastPathComponent().deletingLastPathComponent())
}
}

extension PrivacyDashboardController: WKNavigationDelegate {

public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
subscribeToDataModelChanges()

Expand Down Expand Up @@ -155,7 +179,7 @@ extension PrivacyDashboardController: WKNavigationDelegate {
})
.store(in: &cancellables)
}

private func subscribeToTrackerInfo() {
privacyInfo?.$trackerInfo
.receive(on: DispatchQueue.main)
Expand Down Expand Up @@ -234,53 +258,55 @@ extension PrivacyDashboardController: WKNavigationDelegate {
}

extension PrivacyDashboardController: PrivacyDashboardUserScriptDelegate {

func userScript(_ userScript: PrivacyDashboardUserScript, didRequestOpenSettings target: String) {
let settingsTarget = PrivacyDashboardOpenSettingsTarget(rawValue: target) ?? .general
delegate?.privacyDashboardController(self, didRequestOpenSettings: settingsTarget)
privacyDashboardDelegate?.privacyDashboardController(self, didRequestOpenSettings: settingsTarget)
}

func userScript(_ userScript: PrivacyDashboardUserScript, didChangeProtectionState protectionState: ProtectionState) {
delegate?.privacyDashboardController(self, didChangeProtectionSwitch: protectionState)

switch protectionState.eventOrigin.screen {
case .primaryScreen:
privacyDashboardDelegate?.privacyDashboardController(self, didChangeProtectionSwitch: protectionState)
case .breakageForm:
privacyDashboardReportBrokenSiteDelegate?.privacyDashboardController(self, reportBrokenSiteDidChangeProtectionSwitch: protectionState)
}

}

func userScript(_ userScript: PrivacyDashboardUserScript, didRequestOpenUrlInNewTab url: URL) {
delegate?.privacyDashboardController(self, didRequestOpenUrlInNewTab: url)
privacyDashboardDelegate?.privacyDashboardController(self, didRequestOpenUrlInNewTab: url)
}

func userScriptDidRequestClosing(_ userScript: PrivacyDashboardUserScript) {
#if os(iOS)
delegate?.privacyDashboardControllerDidTapClose(self)
privacyDashboardNavigationDelegate?.privacyDashboardControllerDidTapClose(self)
#endif
}

func userScriptDidRequestShowReportBrokenSite(_ userScript: PrivacyDashboardUserScript) {
#if os(iOS)
delegate?.privacyDashboardControllerDidRequestShowReportBrokenSite(self)
#endif
privacyDashboardDelegate?.privacyDashboardControllerDidRequestShowReportBrokenSite(self)
}

func userScript(_ userScript: PrivacyDashboardUserScript, setHeight height: Int) {
#if os(macOS)
delegate?.privacyDashboardController(self, didSetHeight: height)
#endif
privacyDashboardNavigationDelegate?.privacyDashboardController(self, didSetHeight: height)
}

func userScript(_ userScript: PrivacyDashboardUserScript, didRequestSubmitBrokenSiteReportWithCategory category: String, description: String) {
#if os(macOS)
delegate?.privacyDashboardController(self, didRequestSubmitBrokenSiteReportWithCategory: category, description: description)
#endif
privacyDashboardReportBrokenSiteDelegate?.privacyDashboardController(self, didRequestSubmitBrokenSiteReportWithCategory: category,
description: description)
}

func userScript(_ userScript: PrivacyDashboardUserScript, didSetPermission permission: String, to state: PermissionAuthorizationState) {
#if os(macOS)
delegate?.privacyDashboardController(self, didSetPermission: permission, to: state)
privacyDashboardDelegate?.privacyDashboardController(self, didSetPermission: permission, to: state)
#endif
}

func userScript(_ userScript: PrivacyDashboardUserScript, setPermission permission: String, paused: Bool) {
#if os(macOS)
delegate?.privacyDashboardController(self, setPermission: permission, paused: paused)
privacyDashboardDelegate?.privacyDashboardController(self, setPermission: permission, paused: paused)
#endif
}
}
2 changes: 1 addition & 1 deletion Sources/PrivacyDashboard/PrivacyInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public final class PrivacyInfo {
self.url = url
self.parentEntity = parentEntity
self.protectionStatus = protectionStatus

trackerInfo = TrackerInfo()
}

Expand Down
Loading

0 comments on commit 074af9d

Please sign in to comment.