Skip to content

Commit

Permalink
Merge branch 'main' into bartek/attribution-fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
bwaresiak committed Nov 5, 2024
2 parents 4b76459 + 19f1e5c commit 5ada9b5
Show file tree
Hide file tree
Showing 17 changed files with 385 additions and 92 deletions.
9 changes: 6 additions & 3 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates

version: 2
updates:
- package-ecosystem: "gitsubmodule" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "daily"
- package-ecosystem: "swift" # For Swift package updates
directory: "/" # Location of Package.swift file
schedule:
interval: "daily"
ignore:
- dependency-name: "GRDB"
16 changes: 8 additions & 8 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/duckduckgo/content-scope-scripts",
"state" : {
"revision" : "b74549bd869fdecc16fad851f2f608b1724764df",
"version" : "6.25.0"
"revision" : "48fee2508995d4ac02d18b3d55424adedcb4ce4f",
"version" : "6.28.0"
}
},
{
"identity" : "duckduckgo-autofill",
"kind" : "remoteSourceControl",
"location" : "https://github.com/duckduckgo/duckduckgo-autofill.git",
"state" : {
"revision" : "945ac09a0189dc6736db617867fde193ea984b20",
"version" : "15.0.0"
"revision" : "c992041d16ec10d790e6204dce9abf9966d1363c",
"version" : "15.1.0"
}
},
{
Expand All @@ -50,8 +50,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/duckduckgo/privacy-dashboard",
"state" : {
"revision" : "9de2b2aa317a48d3ee31116dc15b0feeb2cc9414",
"version" : "5.3.0"
"revision" : "53fd1a0f8d91fcf475d9220f810141007300dffd",
"version" : "7.1.1"
}
},
{
Expand All @@ -77,8 +77,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/duckduckgo/sync_crypto",
"state" : {
"revision" : "2ab6ab6f0f96b259c14c2de3fc948935fc16ac78",
"version" : "0.2.0"
"revision" : "0c8bf3c0e75591bc366407b9d7a73a9fcfc7736f",
"version" : "0.3.0"
}
},
{
Expand Down
8 changes: 4 additions & 4 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,13 @@ let package = Package(
.library(name: "Onboarding", targets: ["Onboarding"])
],
dependencies: [
.package(url: "https://github.com/duckduckgo/duckduckgo-autofill.git", exact: "15.0.0"),
.package(url: "https://github.com/duckduckgo/duckduckgo-autofill.git", exact: "15.1.0"),
.package(url: "https://github.com/duckduckgo/GRDB.swift.git", exact: "2.4.0"),
.package(url: "https://github.com/duckduckgo/TrackerRadarKit", exact: "3.0.0"),
.package(url: "https://github.com/duckduckgo/sync_crypto", exact: "0.2.0"),
.package(url: "https://github.com/duckduckgo/sync_crypto", exact: "0.3.0"),
.package(url: "https://github.com/gumob/PunycodeSwift.git", exact: "3.0.0"),
.package(url: "https://github.com/duckduckgo/privacy-dashboard", exact: "5.3.0"),
.package(url: "https://github.com/duckduckgo/content-scope-scripts", exact: "6.25.0"),
.package(url: "https://github.com/duckduckgo/privacy-dashboard", exact: "7.1.1"),
.package(url: "https://github.com/duckduckgo/content-scope-scripts", exact: "6.28.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/1024jp/GzipSwift.git", exact: "6.0.1")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public enum PrivacyFeature: String {
case networkProtection
case aiChat
case contextualOnboarding
case adAttributionReporting
}

/// An abstraction to be implemented by any "subfeature" of a given `PrivacyConfiguration` feature.
Expand Down Expand Up @@ -152,6 +153,7 @@ public enum PrivacyProSubfeature: String, Equatable, PrivacySubfeature {
case isLaunchedOverride
case isLaunchedOverrideStripe
case useUnifiedFeedback
case setAccessTokenCookieForSubscriptionDomains
}

public enum SslCertificatesSubfeature: String, PrivacySubfeature {
Expand Down
2 changes: 1 addition & 1 deletion Sources/DuckPlayer/DuckPlayerURLExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ extension URL {

public var isYoutube: Bool {
guard let host else { return false }
return host == "m.youtube.com" || host == "youtube.com"
return host == "m.youtube.com" || host == "youtube.com" || host == "www.youtube.com"
}

public func addingWatchInYoutubeQueryParameter() -> URL? {
Expand Down
15 changes: 15 additions & 0 deletions Sources/History/HistoryCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public protocol HistoryCoordinating: AnyObject {
func burnDomains(_ baseDomains: Set<String>, tld: TLD, completion: @escaping (Set<URL>) -> Void)
func burnVisits(_ visits: [Visit], completion: @escaping () -> Void)

func removeUrlEntry(_ url: URL, completion: ((Error?) -> Void)?)
}

/// Coordinates access to History. Uses its own queue with high qos for all operations.
Expand Down Expand Up @@ -191,6 +192,20 @@ final public class HistoryCoordinator: HistoryCoordinating {
}
}

public enum EntryRemovalError: Error {
case notAvailable
}

public func removeUrlEntry(_ url: URL, completion: ((Error?) -> Void)? = nil) {
guard let historyDictionary = historyDictionary else { return }
guard let entry = historyDictionary[url] else {
completion?(EntryRemovalError.notAvailable)
return
}

removeEntries([entry], completionHandler: completion)
}

var cleaningDate: Date { .monthAgo }

@objc private func cleanOld() {
Expand Down
68 changes: 66 additions & 2 deletions Sources/NetworkProtection/PacketTunnelProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ open class PacketTunnelProvider: NEPacketTunnelProvider {
case rekeyAttempt(_ step: RekeyAttemptStep)
case failureRecoveryAttempt(_ step: FailureRecoveryStep)
case serverMigrationAttempt(_ step: ServerMigrationAttemptStep)
case malformedErrorDetected(_ error: Error)
}

public enum AttemptStep: CustomDebugStringConvertible {
Expand Down Expand Up @@ -710,7 +711,13 @@ open class PacketTunnelProvider: NEPacketTunnelProvider {
Logger.networkProtection.log("🔴 Stopping VPN due to no auth token")
await attemptShutdownDueToRevokedAccess()

throw error
// Check that the error is valid and able to be re-thrown to the OS before shutting the tunnel down
if let wrappedError = wrapped(error: error) {
providerEvents.fire(.malformedErrorDetected(error))
throw wrappedError
} else {
throw error
}
}

do {
Expand All @@ -737,7 +744,14 @@ open class PacketTunnelProvider: NEPacketTunnelProvider {
self.knownFailureStore.lastKnownFailure = KnownFailure(error)

providerEvents.fire(.tunnelStartAttempt(.failure(error)))
throw error

// Check that the error is valid and able to be re-thrown to the OS before shutting the tunnel down
if let wrappedError = wrapped(error: error) {
providerEvents.fire(.malformedErrorDetected(error))
throw wrappedError
} else {
throw error
}
}
}

Expand Down Expand Up @@ -1815,6 +1829,56 @@ open class PacketTunnelProvider: NEPacketTunnelProvider {
snoozeTimingStore.reset()
}

// MARK: - Error Validation

enum InvalidDiagnosticError: Error, CustomNSError {
case errorWithInvalidUnderlyingError(Error)

var errorCode: Int {
switch self {
case .errorWithInvalidUnderlyingError(let error):
return (error as NSError).code
}
}

var localizedDescription: String {
switch self {
case .errorWithInvalidUnderlyingError(let error):
return "Error '\(type(of: error))', message: \(error.localizedDescription)"
}
}

var errorUserInfo: [String: Any] {
switch self {
case .errorWithInvalidUnderlyingError(let error):
let newError = NSError(domain: (error as NSError).domain, code: (error as NSError).code)
return [NSUnderlyingErrorKey: newError]
}
}
}

/// Wraps an error instance in a new error type in cases where it is malformed; i.e., doesn't use an `NSError` instance for its underlying error, etc.
private func wrapped(error: Error) -> Error? {
if containsValidUnderlyingError(error) {
return nil
} else {
return InvalidDiagnosticError.errorWithInvalidUnderlyingError(error)
}
}

private func containsValidUnderlyingError(_ error: Error) -> Bool {
let nsError = error as NSError

if let underlyingError = nsError.userInfo[NSUnderlyingErrorKey] as? Error {
return containsValidUnderlyingError(underlyingError)
} else if nsError.userInfo[NSUnderlyingErrorKey] != nil {
// If `NSUnderlyingErrorKey` exists but is not an `Error`, return false
return false
}

return true
}

}

extension WireGuardAdapterError: LocalizedError, CustomDebugStringConvertible {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public struct ContextualDaxDialogContent: View {
public let message: NSAttributedString
let list: [ContextualOnboardingListItem]
let listAction: ((_ item: ContextualOnboardingListItem) -> Void)?
let imageName: String?
let customView: AnyView?
let customActionView: AnyView?
let orientation: Orientation

Expand All @@ -54,7 +54,7 @@ public struct ContextualDaxDialogContent: View {
messageFont: Font? = nil,
list: [ContextualOnboardingListItem] = [],
listAction: ((_: ContextualOnboardingListItem) -> Void)? = nil,
imageName: String? = nil,
customView: AnyView? = nil,
customActionView: AnyView? = nil
) {
self.title = title
Expand All @@ -63,7 +63,7 @@ public struct ContextualDaxDialogContent: View {
self.messageFont = messageFont
self.list = list
self.listAction = listAction
self.imageName = imageName
self.customView = customView
self.customActionView = customActionView
self.orientation = orientation

Expand All @@ -75,8 +75,8 @@ public struct ContextualDaxDialogContent: View {
if !list.isEmpty {
itemsToAnimate.append(.list)
}
if imageName != nil {
itemsToAnimate.append(.image)
if customView != nil {
itemsToAnimate.append(.customView)
}
if customActionView != nil {
itemsToAnimate.append(.button)
Expand Down Expand Up @@ -124,8 +124,8 @@ public struct ContextualDaxDialogContent: View {
VStack(alignment: .leading, spacing: 16) {
listView
.visibility(nonTypingAnimatableItems.contains(.list) ? .visible : .invisible)
imageView
.visibility(nonTypingAnimatableItems.contains(.image) ? .visible : .invisible)
extraView
.visibility(nonTypingAnimatableItems.contains(.customView) ? .visible : .invisible)
actionView
.visibility(nonTypingAnimatableItems.contains(.button) ? .visible : .invisible)
}
Expand Down Expand Up @@ -166,13 +166,9 @@ public struct ContextualDaxDialogContent: View {
}

@ViewBuilder
private var imageView: some View {
if let imageName {
HStack {
Spacer()
Image(imageName)
Spacer()
}
private var extraView: some View {
if let customView {
customView
}
}

Expand All @@ -187,7 +183,7 @@ public struct ContextualDaxDialogContent: View {
case title
case message
case list
case image
case customView
case button
}
}
Expand All @@ -196,7 +192,7 @@ struct NonTypingAnimatableItems: OptionSet {
let rawValue: Int

static let list = NonTypingAnimatableItems(rawValue: 1 << 0)
static let image = NonTypingAnimatableItems(rawValue: 1 << 1)
static let customView = NonTypingAnimatableItems(rawValue: 1 << 1)
static let button = NonTypingAnimatableItems(rawValue: 1 << 2)
}

Expand Down Expand Up @@ -225,8 +221,8 @@ extension ContextualDaxDialogContent {
break
case .list:
nonTypingAnimatableItems.insert(.list)
case .image:
nonTypingAnimatableItems.insert(.image)
case .customView:
nonTypingAnimatableItems.insert(.customView)
case .button:
nonTypingAnimatableItems.insert(.button)
}
Expand Down Expand Up @@ -274,10 +270,18 @@ enum Metrics {

#Preview("Intro Dialog - title, text, image and button") {
let contextualText = NSMutableAttributedString(string: "Sabrina is the best\n\nBelieve me! ☝️")
let extraView = {
HStack {
Spacer()
Image("Sync-Desktop-New-128")
Spacer()
}
}()

return ContextualDaxDialogContent(
title: "Who is the best?",
message: contextualText,
imageName: "Sync-Desktop-New-128",
customView: AnyView(extraView),
customActionView: AnyView(Button("Got it!", action: {})))
.padding()
.preferredColorScheme(.light)
Expand Down
Loading

0 comments on commit 5ada9b5

Please sign in to comment.