Skip to content

Commit

Permalink
Collect extra metadata (#2622)
Browse files Browse the repository at this point in the history
  • Loading branch information
quanganhdo authored Mar 25, 2024
1 parent e8479dd commit 96ceae1
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 21 deletions.
2 changes: 1 addition & 1 deletion DuckDuckGo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -10033,7 +10033,7 @@
repositoryURL = "https://github.com/DuckDuckGo/BrowserServicesKit";
requirement = {
kind = exactVersion;
version = 129.1.4;
version = 129.1.6;
};
};
B6F997C22B8F374300476735 /* XCRemoteSwiftPackageReference "apple-toolbox" */ = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/DuckDuckGo/BrowserServicesKit",
"state" : {
"revision" : "91b012d9450af211f7c47b9fde811e3a8292b16b",
"version" : "129.1.4"
"branch" : "anh/pp/add-metadata",
"revision" : "0cba47cf651175806bc151366605f8b19802d3ee"
}
},
{
Expand Down
71 changes: 53 additions & 18 deletions DuckDuckGo/Feedback/VPNMetadataCollector.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import Common
import NetworkProtection
import NetworkExtension
import Network
import Subscription

struct VPNMetadata: Encodable {

Expand Down Expand Up @@ -61,11 +62,27 @@ struct VPNMetadata: Encodable {
let selectedServer: String
}

struct PrivacyProInfo: Encodable {
// swiftlint:disable nesting
enum Source: String, Encodable {
case `internal`
case waitlist
case other
}
// swiftlint:enable nesting

let enableSource: Source
let betaParticipant: Bool
let hasToken: Bool
let subscriptionActive: Bool
}

let appInfo: AppInfo
let deviceInfo: DeviceInfo
let networkInfo: NetworkInfo
let vpnState: VPNState
let vpnSettingsState: VPNSettingsState
let privacyProInfo: PrivacyProInfo

func toPrettyPrintedJSON() -> String? {
let encoder = JSONEncoder()
Expand Down Expand Up @@ -99,15 +116,21 @@ protocol VPNMetadataCollector {
final class DefaultVPNMetadataCollector: VPNMetadataCollector {
private let statusObserver: ConnectionStatusObserver
private let serverInfoObserver: ConnectionServerInfoObserver
private let accessManager: NetworkProtectionAccessController
private let tokenStore: NetworkProtectionTokenStore
private let settings: VPNSettings
private let defaults: UserDefaults

init(statusObserver: ConnectionStatusObserver = ConnectionStatusObserverThroughSession(),
serverInfoObserver: ConnectionServerInfoObserver = ConnectionServerInfoObserverThroughSession(),
networkProtectionAccessManager: NetworkProtectionAccessController = NetworkProtectionAccessController(),
tokenStore: NetworkProtectionTokenStore = NetworkProtectionKeychainTokenStore(),
settings: VPNSettings = .init(defaults: .networkProtectionGroupDefaults),
defaults: UserDefaults = .networkProtectionGroupDefaults) {
self.statusObserver = statusObserver
self.serverInfoObserver = serverInfoObserver
self.accessManager = networkProtectionAccessManager
self.tokenStore = tokenStore
self.settings = settings
self.defaults = defaults
}
Expand All @@ -118,13 +141,15 @@ final class DefaultVPNMetadataCollector: VPNMetadataCollector {
let networkInfoMetadata = await collectNetworkInformation()
let vpnState = await collectVPNState()
let vpnSettingsState = collectVPNSettingsState()
let privacyProInfo = collectPrivacyProInfo()

return VPNMetadata(
appInfo: appInfoMetadata,
deviceInfo: deviceInfoMetadata,
networkInfo: networkInfoMetadata,
vpnState: vpnState,
vpnSettingsState: vpnSettingsState
vpnSettingsState: vpnSettingsState,
privacyProInfo: privacyProInfo
)
}

Expand Down Expand Up @@ -242,7 +267,7 @@ final class DefaultVPNMetadataCollector: VPNMetadataCollector {
}

func collectVPNSettingsState() -> VPNMetadata.VPNSettingsState {
return .init(
.init(
connectOnLoginEnabled: settings.connectOnLogin,
includeAllNetworksEnabled: settings.includeAllNetworks,
enforceRoutesEnabled: settings.enforceRoutes,
Expand All @@ -251,25 +276,35 @@ final class DefaultVPNMetadataCollector: VPNMetadataCollector {
selectedServer: settings.selectedServer.stringValue ?? "automatic"
)
}
}

extension Network.NWPath {
/// A description that's safe from a privacy standpoint.
///
/// Ref: https://app.asana.com/0/0/1206712493935053/1206712516729780/f
///
var anonymousDescription: String {
var description = "NWPath("

description += "status: \(status), "

if #available(iOS 14.2, *), case .unsatisfied = status {
description += "unsatisfiedReason: \(unsatisfiedReason), "
func collectPrivacyProInfo() -> VPNMetadata.PrivacyProInfo {
let accessType = accessManager.networkProtectionAccessType()
var hasToken: Bool {
guard let token = try? tokenStore.fetchToken(),
!token.hasPrefix(NetworkProtectionKeychainTokenStore.authTokenPrefix) else {
return false
}
return true
}

description += "availableInterfaces: \(availableInterfaces)"
description += ")"
return .init(
enableSource: .init(from: accessManager.networkProtectionAccessType()),
betaParticipant: accessType == .waitlistJoined,
hasToken: hasToken,
subscriptionActive: AccountManager(subscriptionAppGroup: Bundle.main.appGroup(bundle: .subs)).accessToken != nil
)
}
}

return description
extension VPNMetadata.PrivacyProInfo.Source {
init(from accessType: NetworkProtectionAccessType) {
switch accessType {
case .inviteCodeInvited:
self = .internal
case .waitlistInvited:
self = .waitlist
default:
self = .other
}
}
}

0 comments on commit 96ceae1

Please sign in to comment.