Skip to content

Commit

Permalink
Merge branch 'main' into brad/new-breakage-parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
SlayterDev committed Mar 21, 2024
2 parents cde4582 + cb3b645 commit b4b2607
Show file tree
Hide file tree
Showing 16 changed files with 80 additions and 29 deletions.
2 changes: 1 addition & 1 deletion DuckDuckGo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14109,7 +14109,7 @@
repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit";
requirement = {
kind = revision;
revision = a63e7129d7ff9d5bb7241ce98ed61b701c07cd66;
revision = 449a86715ba9018b9e94fccfecc96566d7e363c5;
};
};
AA06B6B52672AF8100F541C5 /* XCRemoteSwiftPackageReference "Sparkle" */ = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/duckduckgo/BrowserServicesKit",
"state" : {
"revision" : "a63e7129d7ff9d5bb7241ce98ed61b701c07cd66"
"revision" : "449a86715ba9018b9e94fccfecc96566d7e363c5"
}
},
{
Expand Down
1 change: 1 addition & 0 deletions DuckDuckGo/Autofill/ContentOverlayViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ extension ContentOverlayViewController: SecureVaultManagerDelegate {
promptUserToAutofillCredentialsForDomain domain: String,
withAccounts accounts: [SecureVaultModels.WebsiteAccount],
withTrigger trigger: AutofillUserScript.GetTriggerType,
onAccountSelected account: @escaping (SecureVaultModels.WebsiteAccount?) -> Void,
completionHandler: @escaping (SecureVaultModels.WebsiteAccount?) -> Void) {
// no-op on macOS
}
Expand Down
6 changes: 6 additions & 0 deletions DuckDuckGo/LoginItems/LoginItemsManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ final class LoginItemsManager {
}
}

func isAnyEnabled(_ items: Set<LoginItem>) -> Bool {
return items.contains(where: { item in
item.status == .enabled
})
}

private func handleError(for item: LoginItem, action: Action, error: NSError) {
let event = Pixel.Event.Debug.loginItemUpdateError(
loginItemBundleID: item.agentBundleID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,19 +85,15 @@ final class NetworkProtectionAppEvents {
}

private func restartNetworkProtectionIfVersionChanged(using loginItemsManager: LoginItemsManager) {
let versionStore = NetworkProtectionLastVersionRunStore()

// should‘ve been run at least once with NetP enabled
guard versionStore.lastVersionRun != nil else {
os_log(.info, log: .networkProtection, "No last version found for the NetP login items, skipping update")
return
}

// We want to restart the VPN menu app to make sure it's always on the latest.
restartNetworkProtectionMenu(using: loginItemsManager)
}

private func restartNetworkProtectionMenu(using loginItemsManager: LoginItemsManager) {
guard loginItemsManager.isAnyEnabled(LoginItemsManager.networkProtectionLoginItems) else {
return
}

loginItemsManager.restartLoginItems(LoginItemsManager.networkProtectionLoginItems, log: .networkProtection)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,11 @@ final class NetworkProtectionNavBarButtonModel: NSObject, ObservableObject {
}

private func setupIconSubscription() {
iconPublisherCancellable = iconPublisher.$icon.sink { [weak self] icon in
self?.buttonImage = self?.buttonImageFromWaitlistState(icon: icon)
}
iconPublisherCancellable = iconPublisher.$icon
.receive(on: DispatchQueue.main)
.sink { [weak self] icon in
self?.buttonImage = self?.buttonImageFromWaitlistState(icon: icon)
}
}

/// Temporary override used for the NetP waitlist beta, as a different asset is used for users who are invited to join the beta but haven't yet accepted.
Expand Down
1 change: 1 addition & 0 deletions DuckDuckGo/Tab/TabExtensions/AutofillTabExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ extension AutofillTabExtension: SecureVaultManagerDelegate {
promptUserToAutofillCredentialsForDomain domain: String,
withAccounts accounts: [SecureVaultModels.WebsiteAccount],
withTrigger trigger: AutofillUserScript.GetTriggerType,
onAccountSelected account: @escaping (SecureVaultModels.WebsiteAccount?) -> Void,
completionHandler: @escaping (SecureVaultModels.WebsiteAccount?) -> Void) {
// no-op on macOS
}
Expand Down
8 changes: 5 additions & 3 deletions DuckDuckGo/VPNFeedbackForm/VPNMetadataCollector.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ struct VPNMetadata: Encodable {

struct AppInfo: Encodable {
let appVersion: String
let lastVersionRun: String
let lastAgentVersionRun: String
let lastExtensionVersionRun: String
let isInternalUser: Bool
let isInApplicationsDirectory: Bool
}
Expand Down Expand Up @@ -154,13 +155,14 @@ final class DefaultVPNMetadataCollector: VPNMetadataCollector {

private func collectAppInfoMetadata() -> VPNMetadata.AppInfo {
let appVersion = AppVersion.shared.versionAndBuildNumber
let versionStore = NetworkProtectionLastVersionRunStore()
let versionStore = NetworkProtectionLastVersionRunStore(userDefaults: .netP)
let isInternalUser = NSApp.delegateTyped.internalUserDecider.isInternalUser
let isInApplicationsDirectory = Bundle.main.isInApplicationsDirectory

return .init(
appVersion: appVersion,
lastVersionRun: versionStore.lastVersionRun ?? "Unknown",
lastAgentVersionRun: versionStore.lastAgentVersionRun ?? "none",
lastExtensionVersionRun: versionStore.lastExtensionVersionRun ?? "none",
isInternalUser: isInternalUser,
isInApplicationsDirectory: isInApplicationsDirectory
)
Expand Down
9 changes: 7 additions & 2 deletions DuckDuckGoVPN/NetworkExtensionController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
//

import Foundation
import NetworkProtection
import NetworkProtectionUI

#if NETP_SYSTEM_EXTENSION
Expand All @@ -32,11 +33,13 @@ final class NetworkExtensionController {

#if NETP_SYSTEM_EXTENSION
private let systemExtensionManager: SystemExtensionManager
private let defaults: UserDefaults
#endif

init(extensionBundleID: String) {
init(extensionBundleID: String, defaults: UserDefaults = .netP) {
#if NETP_SYSTEM_EXTENSION
systemExtensionManager = SystemExtensionManager(extensionBundleID: extensionBundleID)
self.defaults = defaults
#endif
}

Expand All @@ -46,9 +49,11 @@ extension NetworkExtensionController {

func activateSystemExtension(waitingForUserApproval: @escaping () -> Void) async throws {
#if NETP_SYSTEM_EXTENSION
try await systemExtensionManager.activate(
let extensionVersion = try await systemExtensionManager.activate(
waitingForUserApproval: waitingForUserApproval)

NetworkProtectionLastVersionRunStore(userDefaults: defaults).lastExtensionVersionRun = extensionVersion

try? await Task.sleep(nanoseconds: 300 * NSEC_PER_MSEC)
#endif
}
Expand Down
8 changes: 4 additions & 4 deletions DuckDuckGoVPN/VPNAppEventsHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,20 @@ final class VPNAppEventsHandler {

func appDidFinishLaunching() {
let currentVersion = AppVersion.shared.versionAndBuildNumber
let versionStore = NetworkProtectionLastVersionRunStore()
let versionStore = NetworkProtectionLastVersionRunStore(userDefaults: .netP)
defer {
versionStore.lastVersionRun = currentVersion
versionStore.lastAgentVersionRun = currentVersion
}

let restartTunnel = {
os_log(.info, log: .networkProtection, "App updated from %{public}s to %{public}s: updating login items", versionStore.lastVersionRun ?? "null", currentVersion)
os_log(.info, log: .networkProtection, "App updated from %{public}s to %{public}s: updating login items", versionStore.lastAgentVersionRun ?? "null", currentVersion)
self.restartTunnel()
}

#if DEBUG || REVIEW // Since DEBUG and REVIEW builds may not change version No. we want them to always reset.
restartTunnel()
#else
if versionStore.lastVersionRun != currentVersion {
if versionStore.lastAgentVersionRun != currentVersion {
restartTunnel()
}
#endif
Expand Down
2 changes: 1 addition & 1 deletion LocalPackages/DataBrokerProtection/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ let package = Package(
targets: ["DataBrokerProtection"])
],
dependencies: [
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", revision: "a63e7129d7ff9d5bb7241ce98ed61b701c07cd66"),
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", revision: "449a86715ba9018b9e94fccfecc96566d7e363c5"),
.package(path: "../PixelKit"),
.package(path: "../SwiftUIExtensions"),
.package(path: "../XPCHelper"),
Expand Down
2 changes: 1 addition & 1 deletion LocalPackages/NetworkProtectionMac/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ let package = Package(
.library(name: "NetworkProtectionUI", targets: ["NetworkProtectionUI"])
],
dependencies: [
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", revision: "a63e7129d7ff9d5bb7241ce98ed61b701c07cd66"),
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", revision: "449a86715ba9018b9e94fccfecc96566d7e363c5"),
.package(path: "../XPCHelper"),
.package(path: "../SwiftUIExtensions"),
.package(path: "../LoginItems"),
Expand Down
2 changes: 1 addition & 1 deletion LocalPackages/SubscriptionUI/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ let package = Package(
targets: ["SubscriptionUI"]),
],
dependencies: [
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", revision: "a63e7129d7ff9d5bb7241ce98ed61b701c07cd66"),
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", revision: "449a86715ba9018b9e94fccfecc96566d7e363c5"),
.package(path: "../SwiftUIExtensions")
],
targets: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ public struct SystemExtensionManager {
self.workspace = workspace
}

public func activate(waitingForUserApproval: @escaping () -> Void) async throws {
/// - Returns: The system extension version.
///
public func activate(waitingForUserApproval: @escaping () -> Void) async throws -> String {
/// Documenting a workaround for the issue discussed in https://app.asana.com/0/0/1205275221447702/f
/// Background: For a lot of users, the system won't show the system-extension-blocked alert if there's a previous request
/// to activate the extension. You can see active requests in your console using command `systemextensionsctl list`.
Expand All @@ -62,11 +64,14 @@ public struct SystemExtensionManager {
openSystemSettingsSecurity()
}

return try await SystemExtensionRequest.activationRequest(
let activationRequest = SystemExtensionRequest.activationRequest(
forExtensionWithIdentifier: extensionBundleID,
manager: manager,
waitingForUserApproval: waitingForUserApproval)
.submit()

try await activationRequest.submit()

return activationRequest.version ?? "unknown"
}

public func deactivate() async throws {
Expand Down Expand Up @@ -113,6 +118,7 @@ final class SystemExtensionRequest: NSObject {
private let request: OSSystemExtensionRequest
private let manager: OSSystemExtensionManager
private let waitingForUserApproval: (() -> Void)?
private(set) var version: String?

private var continuation: CheckedContinuation<Void, Error>?

Expand Down Expand Up @@ -144,12 +150,30 @@ final class SystemExtensionRequest: NSObject {
manager.submitRequest(request)
}
}

private func updateVersion(to version: String) {
self.version = version
}

private func updateVersionNumberIfMissing() {
guard version == nil,
let versionString = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String else {
return
}

var extensionVersion = versionString

if let buildString = Bundle.main.infoDictionary?[kCFBundleVersionKey as String] as? String {
extensionVersion = extensionVersion + "." + buildString
}
}
}

extension SystemExtensionRequest: OSSystemExtensionRequestDelegate {

func request(_ request: OSSystemExtensionRequest, actionForReplacingExtension existing: OSSystemExtensionProperties, withExtension ext: OSSystemExtensionProperties) -> OSSystemExtensionRequest.ReplacementAction {

updateVersion(to: ext.bundleShortVersion + "." + ext.bundleVersion)
return .replace
}

Expand All @@ -160,6 +184,7 @@ extension SystemExtensionRequest: OSSystemExtensionRequestDelegate {
func request(_ request: OSSystemExtensionRequest, didFinishWithResult result: OSSystemExtensionRequest.Result) {
switch result {
case .completed:
updateVersionNumberIfMissing()
continuation?.resume()
case .willCompleteAfterReboot:
continuation?.resume(throwing: SystemExtensionRequestError.willActivateAfterReboot)
Expand Down
12 changes: 12 additions & 0 deletions UnitTests/DataExport/MockSecureVault.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ final class MockSecureVault<T: AutofillDatabaseProvider>: AutofillSecureVault {
return accountID
}

func updateLastUsedFor(accountId: Int64) throws {
if var account = storedAccounts.first(where: { $0.id == String(accountId) }) {
account.lastUsed = Date()
}
}

func deleteWebsiteCredentialsFor(accountId: Int64) throws {
storedCredentials[accountId] = nil
}
Expand Down Expand Up @@ -298,6 +304,12 @@ class MockDatabaseProvider: AutofillDatabaseProvider {
return _accounts
}

func updateLastUsedForAccountId(_ accountId: Int64) throws {
if var account = _accounts.first(where: { $0.id == String(accountId) }) {
account.lastUsed = Date()
}
}

func deleteWebsiteCredentialsForAccountId(_ accountId: Int64) throws {
self._accounts = self._accounts.filter { $0.id != String(accountId) }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ private class MockVPNMetadataCollector: VPNMetadataCollector {

let appInfo = VPNMetadata.AppInfo(
appVersion: "1.2.3",
lastVersionRun: "1.2.3",
lastAgentVersionRun: "1.2.3",
lastExtensionVersionRun: "1.2.3",
isInternalUser: false,
isInApplicationsDirectory: true
)
Expand Down

0 comments on commit b4b2607

Please sign in to comment.