Skip to content

Commit

Permalink
Breakage report improvements (#566)
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 Nov 23, 2023
1 parent af63158 commit bdac80f
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 121 deletions.
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: "2.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)
}

}
124 changes: 76 additions & 48 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,57 @@ 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)
privacyDashboardDelegate?.privacyDashboardControllerDidRequestShowReportBrokenSite(self)
#endif
}

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 bdac80f

Please sign in to comment.