From 07502b48d0330602d860f2522ce65a2fabbd5680 Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Fri, 10 Nov 2023 12:24:39 +0100 Subject: [PATCH 01/40] Implemented the VPN settings pane --- DuckDuckGo.xcodeproj/project.pbxproj | 20 +++++ .../Images/VPN.imageset/Contents.json | 12 +++ .../VPN.imageset/VPN-Multicolor-16 1.pdf | Bin 0 -> 5105 bytes DuckDuckGo/Common/Localizables/UserText.swift | 4 + .../Model/PreferencesSection.swift | 9 ++- .../Model/VPNPreferencesModel.swift | 75 ++++++++++++++++++ DuckDuckGo/Preferences/View/Preferences.swift | 3 + .../View/PreferencesRootView.swift | 2 + .../Preferences/View/PreferencesVPNView.swift | 71 +++++++++++++++++ 9 files changed, 194 insertions(+), 2 deletions(-) create mode 100644 DuckDuckGo/Assets.xcassets/Images/VPN.imageset/Contents.json create mode 100644 DuckDuckGo/Assets.xcassets/Images/VPN.imageset/VPN-Multicolor-16 1.pdf create mode 100644 DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift create mode 100644 DuckDuckGo/Preferences/View/PreferencesVPNView.swift diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index e7fb513c9b..f12465e150 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -2900,6 +2900,14 @@ 7B5F9A752AE2BE4E002AEBC0 /* PixelKit in Frameworks */ = {isa = PBXBuildFile; productRef = 7B5F9A742AE2BE4E002AEBC0 /* PixelKit */; }; 7B6D98672ADEB4B000CD35FE /* DataBrokerProtectionLoginItemScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B6D98662ADEB4B000CD35FE /* DataBrokerProtectionLoginItemScheduler.swift */; }; 7B74F2482ADEB03900147283 /* PixelKit in Frameworks */ = {isa = PBXBuildFile; productRef = 7B74F2472ADEB03900147283 /* PixelKit */; }; + 7B8BF22B2AFD698C00A9E03E /* PreferencesVPNView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B8BF22A2AFD698C00A9E03E /* PreferencesVPNView.swift */; }; + 7B8BF22C2AFD698C00A9E03E /* PreferencesVPNView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B8BF22A2AFD698C00A9E03E /* PreferencesVPNView.swift */; }; + 7B8BF22D2AFD698C00A9E03E /* PreferencesVPNView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B8BF22A2AFD698C00A9E03E /* PreferencesVPNView.swift */; }; + 7B8BF22E2AFD698C00A9E03E /* PreferencesVPNView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B8BF22A2AFD698C00A9E03E /* PreferencesVPNView.swift */; }; + 7B8BF2302AFD6A1800A9E03E /* VPNPreferencesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B8BF22F2AFD6A1800A9E03E /* VPNPreferencesModel.swift */; }; + 7B8BF2312AFD6A1800A9E03E /* VPNPreferencesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B8BF22F2AFD6A1800A9E03E /* VPNPreferencesModel.swift */; }; + 7B8BF2322AFD6A1800A9E03E /* VPNPreferencesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B8BF22F2AFD6A1800A9E03E /* VPNPreferencesModel.swift */; }; + 7B8BF2332AFD6A1800A9E03E /* VPNPreferencesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B8BF22F2AFD6A1800A9E03E /* VPNPreferencesModel.swift */; }; 7B8C083C2AE1268E00F4C67F /* PixelKit in Frameworks */ = {isa = PBXBuildFile; productRef = 7B8C083B2AE1268E00F4C67F /* PixelKit */; }; 7B934C412A866DD400FC8F9C /* UserDefaults+NetworkProtectionShared.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B934C402A866DD400FC8F9C /* UserDefaults+NetworkProtectionShared.swift */; }; 7B96D0DC2ADFDB8E007E02C8 /* DataBrokerProtectionPixelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B96D0DB2ADFDB8E007E02C8 /* DataBrokerProtectionPixelTests.swift */; }; @@ -4335,6 +4343,8 @@ 7B6EC5E42AE2D8AF004FE6DF /* DuckDuckGoDBPAgentAppStore.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = DuckDuckGoDBPAgentAppStore.xcconfig; sourceTree = ""; }; 7B6EC5E52AE2D8AF004FE6DF /* DuckDuckGoDBPAgent.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = DuckDuckGoDBPAgent.xcconfig; sourceTree = ""; }; 7B76E6852AD5D77600186A84 /* XPCHelper */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = XPCHelper; sourceTree = ""; }; + 7B8BF22A2AFD698C00A9E03E /* PreferencesVPNView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreferencesVPNView.swift; sourceTree = ""; }; + 7B8BF22F2AFD6A1800A9E03E /* VPNPreferencesModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VPNPreferencesModel.swift; sourceTree = ""; }; 7B934C3D2A866CFF00FC8F9C /* NetworkProtectionOnboardingMenu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkProtectionOnboardingMenu.swift; sourceTree = ""; }; 7B934C402A866DD400FC8F9C /* UserDefaults+NetworkProtectionShared.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UserDefaults+NetworkProtectionShared.swift"; sourceTree = ""; }; 7B96D0CF2ADFDA7E007E02C8 /* DuckDuckGoDBPTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DuckDuckGoDBPTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -5610,6 +5620,7 @@ 3776582E27F82E62009A6B35 /* AutofillPreferences.swift */, 37CD54C327F2FDD100F1F7B9 /* DownloadsPreferences.swift */, 37CD54C527F2FDD100F1F7B9 /* AboutModel.swift */, + 7B8BF22F2AFD6A1800A9E03E /* VPNPreferencesModel.swift */, ); path = Model; sourceTree = ""; @@ -5704,6 +5715,7 @@ 379DE4BC27EA31AC002CC3DE /* PreferencesAutofillView.swift */, 37CC53EF27E8D1440028713D /* PreferencesDownloadsView.swift */, 37AFCE9127DB8CAD00471A10 /* PreferencesAboutView.swift */, + 7B8BF22A2AFD698C00A9E03E /* PreferencesVPNView.swift */, ); path = View; sourceTree = ""; @@ -10278,6 +10290,7 @@ 3192A0902A4C4CFF0084EA89 /* NSSavePanelExtension.swift in Sources */, 3192A0912A4C4CFF0084EA89 /* AppPrivacyConfigurationDataProvider.swift in Sources */, BB8705162A96324B003359A2 /* WKBackForwardListExtension.swift in Sources */, + 7B8BF22D2AFD698C00A9E03E /* PreferencesVPNView.swift in Sources */, 318115E52A8A4F3300129796 /* CredentialsCleanupErrorHandling.swift in Sources */, 3192A0922A4C4CFF0084EA89 /* LinkButton.swift in Sources */, 3192A0932A4C4CFF0084EA89 /* TemporaryFileHandler.swift in Sources */, @@ -10567,6 +10580,7 @@ 3192A1942A4C4CFF0084EA89 /* BookmarkList.swift in Sources */, 3192A1952A4C4CFF0084EA89 /* NEOnDemandRuleExtension.swift in Sources */, 31C5FFB92AF64D120008A79F /* DataBrokerProtectionFeatureVisibility.swift in Sources */, + 7B8BF2322AFD6A1800A9E03E /* VPNPreferencesModel.swift in Sources */, 3192A1962A4C4CFF0084EA89 /* BookmarkTableRowView.swift in Sources */, 3192A1972A4C4CFF0084EA89 /* FavoritesView.swift in Sources */, 3192A1982A4C4CFF0084EA89 /* HomePage.swift in Sources */, @@ -10877,6 +10891,7 @@ 3707C71F294B5D2900682A9F /* WKUserContentControllerExtension.swift in Sources */, 3706FB1A293F65D500E42796 /* OutlineSeparatorViewCell.swift in Sources */, 3706FB1B293F65D500E42796 /* SafariDataImporter.swift in Sources */, + 7B8BF2312AFD6A1800A9E03E /* VPNPreferencesModel.swift in Sources */, 3706FB1D293F65D500E42796 /* StatisticsLoader.swift in Sources */, 3793FDD829535EBA00A2E28F /* Assertions.swift in Sources */, 3706FB1E293F65D500E42796 /* WebsiteBreakageReporter.swift in Sources */, @@ -11226,6 +11241,7 @@ 3706FC2F293F65D500E42796 /* MouseOverButton.swift in Sources */, 3706FC30293F65D500E42796 /* FireInfoViewController.swift in Sources */, 3706FC31293F65D500E42796 /* PermissionButton.swift in Sources */, + 7B8BF22C2AFD698C00A9E03E /* PreferencesVPNView.swift in Sources */, 3706FC32293F65D500E42796 /* MoreOptionsMenu.swift in Sources */, 3706FC34293F65D500E42796 /* PermissionAuthorizationViewController.swift in Sources */, 3706FC35293F65D500E42796 /* BookmarkNode.swift in Sources */, @@ -12086,6 +12102,7 @@ 4B957A702AC7AE700062CA31 /* RecentlyClosedCoordinator.swift in Sources */, 4B957A712AC7AE700062CA31 /* URLRequestExtension.swift in Sources */, 4B957A722AC7AE700062CA31 /* FaviconHostReference.swift in Sources */, + 7B8BF22E2AFD698C00A9E03E /* PreferencesVPNView.swift in Sources */, 4B957A732AC7AE700062CA31 /* DownloadsTabExtension.swift in Sources */, 4B957A742AC7AE700062CA31 /* WebsiteBreakageSender.swift in Sources */, 4B957A752AC7AE700062CA31 /* ASN1Parser.swift in Sources */, @@ -12268,6 +12285,7 @@ 4B957B232AC7AE700062CA31 /* WaitlistRootView.swift in Sources */, 4B957B242AC7AE700062CA31 /* YoutubeOverlayUserScript.swift in Sources */, 4B957B252AC7AE700062CA31 /* DictionaryExtension.swift in Sources */, + 7B8BF2332AFD6A1800A9E03E /* VPNPreferencesModel.swift in Sources */, 4B957B262AC7AE700062CA31 /* Publishers.NestedObjectChanges.swift in Sources */, 4B957B272AC7AE700062CA31 /* MenuItemSelectors.swift in Sources */, 4B957B282AC7AE700062CA31 /* FaviconView.swift in Sources */, @@ -12772,6 +12790,7 @@ 31B9226C288054D5001F55B7 /* CookieConsentPopoverManager.swift in Sources */, 4BE65474271FCD40008D1D63 /* PasswordManagementIdentityItemView.swift in Sources */, B6F41031264D2B23003DA42C /* ProgressExtension.swift in Sources */, + 7B8BF2302AFD6A1800A9E03E /* VPNPreferencesModel.swift in Sources */, 4B723E0F26B0006500E14D75 /* CSVParser.swift in Sources */, B6DA44082616B30600DD1EC2 /* PixelDataModel.xcdatamodeld in Sources */, B63BDF7E27FDAA640072D75B /* PrivacyDashboardWebView.swift in Sources */, @@ -12815,6 +12834,7 @@ AA5C8F632591021700748EB7 /* NSApplicationExtension.swift in Sources */, AA9E9A5625A3AE8400D1959D /* NSWindowExtension.swift in Sources */, 7BD3AF5D2A8E7AF1006F9F56 /* KeychainType+ClientDefault.swift in Sources */, + 7B8BF22B2AFD698C00A9E03E /* PreferencesVPNView.swift in Sources */, 370A34B12AB24E3700C77F7C /* SyncDebugMenu.swift in Sources */, AAC5E4C725D6A6E8007F5990 /* BookmarkPopover.swift in Sources */, 37CC53F027E8D1440028713D /* PreferencesDownloadsView.swift in Sources */, diff --git a/DuckDuckGo/Assets.xcassets/Images/VPN.imageset/Contents.json b/DuckDuckGo/Assets.xcassets/Images/VPN.imageset/Contents.json new file mode 100644 index 0000000000..2986a1a8ee --- /dev/null +++ b/DuckDuckGo/Assets.xcassets/Images/VPN.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "VPN-Multicolor-16 1.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/DuckDuckGo/Assets.xcassets/Images/VPN.imageset/VPN-Multicolor-16 1.pdf b/DuckDuckGo/Assets.xcassets/Images/VPN.imageset/VPN-Multicolor-16 1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..12bce6ad4030a4f266150dbc84ab6cc427c6047c GIT binary patch literal 5105 zcmcJTO>ZQ(5r*&mEBdm49l#uZe*lJocsCA$B*;e2&G12)9j_IPG>Ie!j(>fgVzaAT z(ju@9nZqviHd!oIz4fxX-@JeK%@@v;X>zljFMt2XG|yjtIe+!lbh`T>e@=dnAO3W@ z`}p|d900Fm*2Cld>H2m$ygU8-=6JgL{nzu`Z})#4AEtjz&e;B&?K=2EM=zi0qvP#l zP0F^^$jV%7s+B=2ITklR9PcKVOiLlOHW%Z9i#gA?9jwuHFuGilon2lxE~eO=!XB#Y zv*WbQbKXQ(eW~+qq*ipvw%|Agld3D;?{?FpY(^AP8%It#;-e;XppSIABF71=)?y_( z!$38z6kEs{h>J1K)%cujX&s5dwz;osImQC!8}Z4^(hTKLVzV2f3F_;XJjQkUS$tTr z60NVEmHaQ^PbSoyeVW@kCz%p_3<)0;%cMBwl;-n>Rg-*(Db9|(`#ivR*B<(L5bDVyhe)!FFH~sb3Q*}51JyY`}pi?zN)Ib@TvU0Z7 z>N%}Y75BWXf~hguY6DDFESTm}>>+bZ3K=5}S|>LX9_UIUm-9PM?7XR|KzuNXT$Je} zIKgDsqLb7PWb7yF6mt$%ct>3gQ+XzS6pKxH+YzW%#{pTI%y7)%D-+pVy(bMVX9tZG z(nG#JxJnF|n@W`fiw;0nn}o$lf-K>H!qjpPt~ViMC&g+~OoHALq+&x7=0E}-hdCJA zva124L>QVtdLrT3iX2HwDUq;l7?cUc39}6GNv(${*34klu}p}vi6k2z13Sm;GlT31 zRVAdwlQ2;)%?j$$@CD`)T9mCY3u0vJNs3L$V;~X&pD5Iq2ke1;9cjnb>O+sKsB0&! zTewQ3$*-$Du3Fri&fTs$=l++@Epj6pZbGu-pUT@9NYM=MbW274k2+V|<{pIVKQdAf zE`+K{!uyZZWEf7NL9mh<8R0I-{GUiov&7EzB8gNjf=3-xq}d~Zqw3*M^|iST(SwQ> z2A6Ymn=_(?*z#EfJe1;GKt&5QbmDSxF?kX|jDmB%0IBm*sjxI}s(Yq-J%n;_8a<^5 ze87*?Y{MFIY6CZ?-;P9$+g4>OVfA`)1j0v4;cwwdYkc%D=<5iXq%Aw2xvDpilZH?c zdy$*PTBEuwET8wg;%A@&0=4Q5veby2_@0AB5EwPYTq+r{ZOw9?#x;@>!azZhwuaFr zA@eN~3!sSn1`kw|vk@cIyaZjK=7Y!2zLd?#nLPHjA|T7C_=**79xgU%D6FaYFN6>c zsd1@fJWN?sTU63RkRI_EUC6A7CRntkW3CmKa3Y!5L*woqY`V&xlEmnhs_zi~#*(a$WAhAF{w=TV$gGWsv+giaDFshPq>`XrmQ zFOW=!A*KBG30pO^#n~JF#swG8qKS@eAWw%@KEVt}pU!B=u zy7mb+qCucab6imxv6pdueL|7a?hrnX0r^z6B8RKDei=wU)%8FX3QRtCSg6&KJ!>3S z4HC0E@|doO#OOID*V-_l^C0uGJu0$T-yy?**wWYzOl&DO+)?Z5vihKi^fbeSV#2dw zLb2W8Go9ZS}G%30exjlJ$*Sm8U{y+q*oSs;_msG(lx9;{FCs z3(lp5JoFGtQH+5i(k?v5&S1lY&MWJzVLfs6jCJaRv|-OTI&WBiBPiTy!+Mf4^`G=H z%Rmv4gXfr}sh?=~_M{8Oqn%MTuxn%0S4oo!j*?O8V~|P*JEDCG)3xVq?GDoyRrxwI zKE15pY2=g4^8JRkBm)59zulCFlix0k!e(;Yj?SELnue|--&6Wk8% zzBLJ?-=GeEy!n8uvz*{+UiW!>`H8jeh5rvAJ4+;WXGsqDpc`%ne|!CSeZG8ry7cG! z(+?Bx>C?g(`FEzZLDg>yAMdYk z&Zql{k8+1UydxZ+JzQ>2pU [PreferencesSection] { let regularPanes: [PreferencePaneIdentifier] = { #if SUBSCRIPTION - var panes: [PreferencePaneIdentifier] = [.privacy, .subscription, .general, .appearance, .autofill, .downloads] + var panes: [PreferencePaneIdentifier] = [.privacy, .vpn, .subscription, .general, .appearance, .autofill, .downloads] if NSApp.delegateTyped.internalUserDecider.isInternalUser { if let generalIndex = panes.firstIndex(of: .general) { @@ -35,7 +35,7 @@ struct PreferencesSection: Hashable, Identifiable { } } #else - var panes: [PreferencePaneIdentifier] = [.general, .appearance, .privacy, .autofill, .downloads] + var panes: [PreferencePaneIdentifier] = [.vpn, .general, .appearance, .privacy, .autofill, .downloads] if NSApp.delegateTyped.internalUserDecider.isInternalUser { panes.insert(.sync, at: 1) @@ -65,6 +65,7 @@ enum PreferencePaneIdentifier: String, Equatable, Hashable, Identifiable { case sync case appearance case privacy + case vpn #if SUBSCRIPTION case subscription #endif @@ -93,6 +94,8 @@ enum PreferencePaneIdentifier: String, Equatable, Hashable, Identifiable { return UserText.appearance case .privacy: return UserText.privacy + case .vpn: + return UserText.vpn #if SUBSCRIPTION case .subscription: return UserText.subscription @@ -118,6 +121,8 @@ enum PreferencePaneIdentifier: String, Equatable, Hashable, Identifiable { return "Appearance" case .privacy: return "Privacy" + case .vpn: + return "VPN" #if SUBSCRIPTION case .subscription: return "Privacy" diff --git a/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift b/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift new file mode 100644 index 0000000000..3106cadb4b --- /dev/null +++ b/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift @@ -0,0 +1,75 @@ +// +// PrivacyPreferencesModel.swift +// +// Copyright © 2022 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation + +final class VPNPreferencesModel: ObservableObject { + @Published var isAutoconsentEnabled: Bool = true + +/* + @Published + var isLoginDetectionEnabled: Bool { + didSet { + privacySecurityPreferences.loginDetectionEnabled = isLoginDetectionEnabled + } + } + + @Published + var isGPCEnabled: Bool { + didSet { + privacySecurityPreferences.gpcEnabled = isGPCEnabled + } + } + + @Published var isAutoconsentEnabled: Bool { + didSet { + privacySecurityPreferences.autoconsentEnabled = isAutoconsentEnabled + } + } + + @MainActor + func presentManageFireproofSitesDialog() { + let fireproofDomainsWindowController = FireproofDomainsViewController.create().wrappedInWindowController() + + guard let fireproofDomainsWindow = fireproofDomainsWindowController.window, + let parentWindowController = WindowControllersManager.shared.lastKeyMainWindowController + else { + assertionFailure("Privacy Preferences: Failed to present FireproofDomainsViewController") + return + } + + parentWindowController.window?.beginSheet(fireproofDomainsWindow) + } + + @MainActor + func openURL(_ url: URL) { + WindowControllersManager.shared.show(url: url, newTab: true) + } + + init(privacySecurityPreferences: PrivacySecurityPreferences = .shared) { + self.privacySecurityPreferences = privacySecurityPreferences + isLoginDetectionEnabled = privacySecurityPreferences.loginDetectionEnabled + isGPCEnabled = privacySecurityPreferences.gpcEnabled + isAutoconsentEnabled = privacySecurityPreferences.autoconsentEnabled ?? false + } + + private let privacySecurityPreferences: PrivacySecurityPreferences*/ + + init() { + } +} diff --git a/DuckDuckGo/Preferences/View/Preferences.swift b/DuckDuckGo/Preferences/View/Preferences.swift index 739c3eec11..9d3aaaf55f 100644 --- a/DuckDuckGo/Preferences/View/Preferences.swift +++ b/DuckDuckGo/Preferences/View/Preferences.swift @@ -75,6 +75,9 @@ enum Preferences { var body: some View { Toggle(title, isOn: isOn) .fixMultilineScrollableText() + // When the checkbox is disabled we want it to not affect the label color + // Ref: https://app.asana.com/0/0/1205884607941634/f + .foregroundColor(Color.primary) .toggleStyle(.checkbox) } } diff --git a/DuckDuckGo/Preferences/View/PreferencesRootView.swift b/DuckDuckGo/Preferences/View/PreferencesRootView.swift index 076250e3ad..67b46b57ba 100644 --- a/DuckDuckGo/Preferences/View/PreferencesRootView.swift +++ b/DuckDuckGo/Preferences/View/PreferencesRootView.swift @@ -58,6 +58,8 @@ extension Preferences { AppearanceView(model: .shared) case .privacy: PrivacyView(model: PrivacyPreferencesModel()) + case .vpn: + VPNView(model: VPNPreferencesModel()) #if SUBSCRIPTION case .subscription: makeSubscriptionView() diff --git a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift new file mode 100644 index 0000000000..15bf242e5f --- /dev/null +++ b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift @@ -0,0 +1,71 @@ +// +// PreferencesPrivacyView.swift +// +// Copyright © 2022 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import SwiftUI +import SwiftUIExtensions + +extension Preferences { + + struct VPNView: View { + @ObservedObject var model: VPNPreferencesModel + + var body: some View { + VStack(alignment: .leading, spacing: 0) { + + // TITLE + + TextMenuTitle(text: UserText.vpn) + + // SECTION: Manage VPN + + PreferencePaneSection { + TextMenuItemHeader(text: UserText.manageVPNSettingsTitle) + + ToggleMenuItem(title: "Connect on Login", isOn: $model.isAutoconsentEnabled) + TextMenuItemCaption(text: "Automatically connect to the VPN service when you login") + + ToggleMenuItem(title: "Show VPN in menu bar", isOn: $model.isAutoconsentEnabled) + TextMenuItemCaption(text: "Display VPN status in menu bar, next to the Wi-Fi and Battery") + + ToggleMenuItem(title: "Always ON", isOn: $model.isAutoconsentEnabled) + .disabled(true) + TextMenuItemCaption(text: "Display VPN status in menu bar, next to the Wi-Fi and Battery") + + //ToggleMenuItem(title: "Killswitch", isOn: $model.isAutoconsentEnabled) + //TextMenuItemCaption(text: "Display VPN status in menu bar, next to the Wi-Fi and Battery") + + ToggleMenuItem(title: "Exclude Local Networks", isOn: $model.isAutoconsentEnabled) + TextMenuItemCaption(text: "Let local traffic bypass the VPN and connect to devices on your local network, like a printer") + + + ToggleMenuItem(title: "Secure DNS", isOn: $model.isAutoconsentEnabled) + .disabled(true) + TextMenuItemCaption(text: "Prevents DNS leaks to your Internet service provider by routing DNS queries through the VPN tunnel to our own resolver. For your security, this feature cannot be disabled.") + } + + // SECTION: VPN Notifications + + PreferencePaneSection { + TextMenuItemHeader(text: UserText.vpnNotificationsSettingsTitle) + + ToggleMenuItem(title: "Get notified if your connection drops or VPN status changes", isOn: $model.isAutoconsentEnabled) + } + } + } + } +} From f38eb84a6470f6e9ce6888935667cc303aa597d7 Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Fri, 10 Nov 2023 17:18:19 +0100 Subject: [PATCH 02/40] Re-implemented connect on login --- DuckDuckGo.xcodeproj/project.pbxproj | 16 ++++ .../xcshareddata/swiftpm/Package.resolved | 11 +-- .../LoginItem+NetworkProtection.swift | 4 +- .../NetworkProtectionAppEvents.swift | 2 +- .../NetworkProtectionTunnelController.swift | 5 +- .../Model/VPNPreferencesModel.swift | 14 ++- .../Preferences/View/PreferencesVPNView.swift | 2 +- DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift | 19 +++- .../Sources/LoginItems/LoginItem.swift | 8 +- .../LoginItemLaunchInformation.swift | 87 +++++++++++++++++++ 10 files changed, 149 insertions(+), 19 deletions(-) create mode 100644 LocalPackages/LoginItems/Sources/LoginItems/LoginItemLaunchInformation.swift diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 00a95f3d08..385f1816db 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -2909,6 +2909,8 @@ 7B8BF2322AFD6A1800A9E03E /* VPNPreferencesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B8BF22F2AFD6A1800A9E03E /* VPNPreferencesModel.swift */; }; 7B8BF2332AFD6A1800A9E03E /* VPNPreferencesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B8BF22F2AFD6A1800A9E03E /* VPNPreferencesModel.swift */; }; 7B8C083C2AE1268E00F4C67F /* PixelKit in Frameworks */ = {isa = PBXBuildFile; productRef = 7B8C083B2AE1268E00F4C67F /* PixelKit */; }; + 7B90625A2AFE6E54006B8C6E /* LoginItems in Frameworks */ = {isa = PBXBuildFile; productRef = 7B9062592AFE6E54006B8C6E /* LoginItems */; }; + 7B90625C2AFE6E5A006B8C6E /* LoginItems in Frameworks */ = {isa = PBXBuildFile; productRef = 7B90625B2AFE6E5A006B8C6E /* LoginItems */; }; 7B934C412A866DD400FC8F9C /* UserDefaults+NetworkProtectionShared.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B934C402A866DD400FC8F9C /* UserDefaults+NetworkProtectionShared.swift */; }; 7B96D0DC2ADFDB8E007E02C8 /* DataBrokerProtectionPixelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B96D0DB2ADFDB8E007E02C8 /* DataBrokerProtectionPixelTests.swift */; }; 7BA4727D26F01BC400EAA165 /* CoreDataTestUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B9292C42667104B00AD2C21 /* CoreDataTestUtilities.swift */; }; @@ -4326,6 +4328,7 @@ 56D145F029E6F06D00E3488A /* MockBookmarkManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockBookmarkManager.swift; sourceTree = ""; }; 56D6A3D529DB2BAB0055215A /* ContinueSetUpView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContinueSetUpView.swift; sourceTree = ""; }; 7B05829D2A812AC000AC3F7C /* NetworkProtectionOnboardingMenu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkProtectionOnboardingMenu.swift; sourceTree = ""; }; + 7B1631052AFE534600B21188 /* BrowserServicesKit */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = BrowserServicesKit; path = ../../BrowserServicesKit; sourceTree = ""; }; 7B1E819B27C8874900FF0E60 /* ContentOverlayPopover.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentOverlayPopover.swift; sourceTree = ""; }; 7B1E819C27C8874900FF0E60 /* ContentOverlay.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = ContentOverlay.storyboard; sourceTree = ""; }; 7B1E819D27C8874900FF0E60 /* ContentOverlayViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentOverlayViewController.swift; sourceTree = ""; }; @@ -5053,6 +5056,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 7B90625A2AFE6E54006B8C6E /* LoginItems in Frameworks */, 7BEEA5122AD1235B00A9E72B /* NetworkProtectionIPC in Frameworks */, 7BA7CC5F2AD1210C0042E5CE /* Networking in Frameworks */, 7BEEA5162AD1236E00A9E72B /* NetworkProtectionUI in Frameworks */, @@ -5071,6 +5075,7 @@ 7BEEA5142AD1236300A9E72B /* NetworkProtectionIPC in Frameworks */, EE7295EF2A545C12008C0991 /* NetworkProtection in Frameworks */, 4B2D067F2A1334D700DE1F49 /* NetworkProtectionUI in Frameworks */, + 7B90625C2AFE6E5A006B8C6E /* LoginItems in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -5569,6 +5574,7 @@ 378E279C2970217400FCADA2 /* LocalPackages */ = { isa = PBXGroup; children = ( + 7B1631052AFE534600B21188 /* BrowserServicesKit */, 1E862A852A9FBD7000F84D4B /* Account */, 378E279D2970217400FCADA2 /* BuildToolPlugins */, 3192A2702A4C4E330084EA89 /* DataBrokerProtection */, @@ -8820,6 +8826,7 @@ 7BEEA5152AD1236E00A9E72B /* NetworkProtectionUI */, 7BEC182E2AD5D8DC00D30536 /* SystemExtensionManager */, 7BFCB74D2ADE7E1A00DA3EA7 /* PixelKit */, + 7B9062592AFE6E54006B8C6E /* LoginItems */, ); productName = DuckDuckGoAgent; productReference = 4B2D06392A11CFBB00DE1F49 /* DuckDuckGo VPN.app */; @@ -8845,6 +8852,7 @@ 7BA7CC602AD1211C0042E5CE /* Networking */, 7BEEA5132AD1236300A9E72B /* NetworkProtectionIPC */, 7BFCB74F2ADE7E2300DA3EA7 /* PixelKit */, + 7B90625B2AFE6E5A006B8C6E /* LoginItems */, ); productName = DuckDuckGoAgentAppStore; productReference = 4B2D06692A13318400DE1F49 /* DuckDuckGo VPN App Store.app */; @@ -14860,6 +14868,14 @@ isa = XCSwiftPackageProductDependency; productName = PixelKit; }; + 7B9062592AFE6E54006B8C6E /* LoginItems */ = { + isa = XCSwiftPackageProductDependency; + productName = LoginItems; + }; + 7B90625B2AFE6E5A006B8C6E /* LoginItems */ = { + isa = XCSwiftPackageProductDependency; + productName = LoginItems; + }; 7BA59C9A2AE18B49009A97B1 /* SystemExtensionManager */ = { isa = XCSwiftPackageProductDependency; productName = SystemExtensionManager; diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 1d69658009..1d95bd0afe 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -9,15 +9,6 @@ "version" : "3.0.0" } }, - { - "identity" : "browserserviceskit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/duckduckgo/BrowserServicesKit", - "state" : { - "revision" : "c4d5f6df0340f0a5c109dcded9801ab676de7db5", - "version" : "82.3.0" - } - }, { "identity" : "content-scope-scripts", "kind" : "remoteSourceControl", @@ -129,7 +120,7 @@ { "identity" : "trackerradarkit", "kind" : "remoteSourceControl", - "location" : "https://github.com/duckduckgo/TrackerRadarKit.git", + "location" : "https://github.com/duckduckgo/TrackerRadarKit", "state" : { "revision" : "4684440d03304e7638a2c8086895367e90987463", "version" : "1.2.1" diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/LoginItem+NetworkProtection.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/LoginItem+NetworkProtection.swift index ee34e73d09..74e4c40467 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/LoginItem+NetworkProtection.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/LoginItem+NetworkProtection.swift @@ -21,9 +21,9 @@ import LoginItems extension LoginItem { - static let vpnMenu = LoginItem(bundleId: Bundle.main.vpnMenuAgentBundleId, log: .networkProtection) + static let vpnMenu = LoginItem(bundleId: Bundle.main.vpnMenuAgentBundleId, defaults: .shared, log: .networkProtection) #if NETP_SYSTEM_EXTENSION - static let notificationsAgent = LoginItem(bundleId: Bundle.main.notificationsAgentBundleId, log: .networkProtection) + static let notificationsAgent = LoginItem(bundleId: Bundle.main.notificationsAgentBundleId, defaults: .shared, log: .networkProtection) #endif } diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionAppEvents.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionAppEvents.swift index 740c869a6a..ae145c4d85 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionAppEvents.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionAppEvents.swift @@ -169,7 +169,7 @@ final class NetworkProtectionAppEvents { // MARK: - Legacy Login Item and Extension private func removeLegacyLoginItemAndVPNConfiguration() async { - LoginItem(bundleId: legacyAgentBundleID).forceStop() + LoginItem(bundleId: legacyAgentBundleID, defaults: .shared).forceStop() let tunnels = try? await NETunnelProviderManager.loadAllFromPreferences() let tunnel = tunnels?.first { diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift index 916fa99d05..7c968e8ec0 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift @@ -150,7 +150,7 @@ final class NetworkProtectionTunnelController: NetworkProtection.TunnelControlle .store(in: &cancellables) } - /// This is where the tunnel has a chance to handle the settings change locally. + /// This is where the tunnel owner has a chance to handle the settings change locally. /// /// The extension can also handle these changes so not everything needs to be handled here. /// @@ -162,7 +162,8 @@ final class NetworkProtectionTunnelController: NetworkProtection.TunnelControlle try await handleSetEnforceRoutes(enforceRoutes) case .setExcludeLocalNetworks(let excludeLocalNetworks): try await handleSetExcludeLocalNetworks(excludeLocalNetworks) - case .setRegistrationKeyValidity, + case .setConnectOnLogin, + .setRegistrationKeyValidity, .setSelectedServer, .setSelectedEnvironment: // Intentional no-op as this is handled by the extension diff --git a/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift b/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift index 3106cadb4b..fed96a1501 100644 --- a/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift +++ b/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift @@ -17,10 +17,17 @@ // import Foundation +import NetworkProtection final class VPNPreferencesModel: ObservableObject { @Published var isAutoconsentEnabled: Bool = true + @Published var connectOnLogin: Bool { + didSet { + tunnelSettings.connectOnLogin = connectOnLogin + } + } + /* @Published var isLoginDetectionEnabled: Bool { @@ -70,6 +77,11 @@ final class VPNPreferencesModel: ObservableObject { private let privacySecurityPreferences: PrivacySecurityPreferences*/ - init() { + private let tunnelSettings: TunnelSettings + + init(tunnelSettings: TunnelSettings = .init(defaults: .shared)) { + self.tunnelSettings = tunnelSettings + + connectOnLogin = tunnelSettings.connectOnLogin } } diff --git a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift index 15bf242e5f..66661c236f 100644 --- a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift +++ b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift @@ -36,7 +36,7 @@ extension Preferences { PreferencePaneSection { TextMenuItemHeader(text: UserText.manageVPNSettingsTitle) - ToggleMenuItem(title: "Connect on Login", isOn: $model.isAutoconsentEnabled) + ToggleMenuItem(title: "Connect on Login", isOn: $model.connectOnLogin) TextMenuItemCaption(text: "Automatically connect to the VPN service when you login") ToggleMenuItem(title: "Show VPN in menu bar", isOn: $model.isAutoconsentEnabled) diff --git a/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift b/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift index 39492c7f20..df250b0e01 100644 --- a/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift +++ b/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift @@ -19,6 +19,7 @@ import Cocoa import Combine import Common +import LoginItems import Networking import NetworkExtension import NetworkProtection @@ -65,10 +66,12 @@ final class DuckDuckGoVPNAppDelegate: NSObject, NSApplicationDelegate { private lazy var networkExtensionController = NetworkExtensionController(extensionBundleID: networkExtensionBundleID) #endif + private lazy var tunnelSettings = TunnelSettings(defaults: .shared) + private lazy var tunnelController = NetworkProtectionTunnelController( networkExtensionBundleID: networkExtensionBundleID, networkExtensionController: networkExtensionController, - settings: .init(defaults: .shared)) + settings: tunnelSettings) /// An IPC server that provides access to the tunnel controller. /// @@ -162,6 +165,20 @@ final class DuckDuckGoVPNAppDelegate: NSObject, NSApplicationDelegate { onComplete(error) } } + + let launchInformation = LoginItemLaunchInformation(agentBundleID: Bundle.main.bundleIdentifier!, defaults: .shared) + let launchedOnStartup = launchInformation.wasLaunchedByStartup + launchInformation.update() + + if launchedOnStartup { + Task { + let isConnected = await tunnelController.isConnected + + if !isConnected && tunnelSettings.connectOnLogin { + await tunnelController.start() + } + } + } } } diff --git a/LocalPackages/LoginItems/Sources/LoginItems/LoginItem.swift b/LocalPackages/LoginItems/Sources/LoginItems/LoginItem.swift index a826b70904..9e9d53a824 100644 --- a/LocalPackages/LoginItems/Sources/LoginItems/LoginItem.swift +++ b/LocalPackages/LoginItems/Sources/LoginItems/LoginItem.swift @@ -26,6 +26,8 @@ import ServiceManagement public struct LoginItem: Equatable, Hashable { let agentBundleID: String + private let launchInformation: LoginItemLaunchInformation + private let defaults: UserDefaults private let log: OSLog public var isRunning: Bool { @@ -70,8 +72,10 @@ public struct LoginItem: Equatable, Hashable { return Status(SMAppService.loginItem(identifier: agentBundleID).status) } - public init(bundleId: String, log: OSLog = .disabled) { + public init(bundleId: String, defaults: UserDefaults, log: OSLog = .disabled) { self.agentBundleID = bundleId + self.defaults = defaults + self.launchInformation = LoginItemLaunchInformation(agentBundleID: bundleId, defaults: defaults) self.log = log } @@ -83,6 +87,8 @@ public struct LoginItem: Equatable, Hashable { } else { SMLoginItemSetEnabled(agentBundleID as CFString, true) } + + launchInformation.updateLastEnabledTimestamp() } public func disable() throws { diff --git a/LocalPackages/LoginItems/Sources/LoginItems/LoginItemLaunchInformation.swift b/LocalPackages/LoginItems/Sources/LoginItems/LoginItemLaunchInformation.swift new file mode 100644 index 0000000000..a9d30e60f2 --- /dev/null +++ b/LocalPackages/LoginItems/Sources/LoginItems/LoginItemLaunchInformation.swift @@ -0,0 +1,87 @@ +// +// File.swift +// +// +// Created by ddg on 10/11/23. +// + +import Foundation +import AppKit +import os.log + +public struct LoginItemLaunchInformation: Equatable, Hashable { + + private let agentBundleID: String + private let defaults: UserDefaults + private let launchRecencyThreshold = 5.0 + + public init(agentBundleID: String, defaults: UserDefaults) { + self.agentBundleID = agentBundleID + self.defaults = defaults + } + + // MARK: - Launch Information + + private func systemBootTime() -> Date { + var tv = timeval() + var tvSize = MemoryLayout.size + let err = sysctlbyname("kern.boottime", &tv, &tvSize, nil, 0) + guard err == 0, tvSize == MemoryLayout.size else { + return Date(timeIntervalSince1970: 0) + } + return Date(timeIntervalSince1970: Double(tv.tv_sec) + Double(tv.tv_usec) / 1_000_000.0) + } + + /// Lets the login item app know if it was launched by the computer startup. + /// + public var wasLaunchedByStartup: Bool { + let lastSystemBootTime = self.systemBootTime() + let lastRunTime = Date(timeIntervalSince1970: lastRunTimestamp) + let lastEnabledTime = Date(timeIntervalSince1970: lastEnabledTimestamp) + + return lastSystemBootTime > lastRunTime + && lastSystemBootTime > lastEnabledTime + } + + /// The login item app should call this after checking `wasLaunchedByStartup`. + /// + public func update() { + updateLastRunTimestamp() + } + + // MARK: - Last Enabled + + private static let loginItemLastEnabledTimestampKey = "loginItemLastEnabledTimestampKey" + + private func lastEnabledKey(forAgentBundleID agentBundleID: String) -> String { + Self.loginItemLastEnabledTimestampKey + "_" + agentBundleID + } + + var lastEnabledTimestamp: TimeInterval { + defaults.double(forKey: lastEnabledKey(forAgentBundleID: agentBundleID)) + } + + func updateLastEnabledTimestamp() { + defaults.set( + Date().timeIntervalSince1970, + forKey: lastEnabledKey(forAgentBundleID: agentBundleID)) + } + + // MARK: - Last Run + + private static let loginItemLastRunTimestampKey = "loginItemLastRunTimestampKey" + + private func lastRunKey(forAgentBundleID agentBundleID: String) -> String { + Self.loginItemLastRunTimestampKey + "_" + agentBundleID + } + + var lastRunTimestamp: TimeInterval { + defaults.double(forKey: lastRunKey(forAgentBundleID: agentBundleID)) + } + + func updateLastRunTimestamp() { + defaults.set( + Date().timeIntervalSince1970, + forKey: lastRunKey(forAgentBundleID: agentBundleID)) + } +} From e3c199a6de4db162b4996f7b590c5171fb3c7d6d Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Mon, 13 Nov 2023 14:19:13 +0100 Subject: [PATCH 03/40] Implements the option to show the menu, brings several other improvements --- .../NetworkProtectionTunnelController.swift | 5 +- .../Model/PreferencesSection.swift | 6 ++- .../Model/VPNPreferencesModel.swift | 47 +++---------------- .../Preferences/View/PreferencesVPNView.swift | 3 +- DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift | 25 +++++++++- 5 files changed, 38 insertions(+), 48 deletions(-) diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift index 7c968e8ec0..0c1da51ab5 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift @@ -165,8 +165,9 @@ final class NetworkProtectionTunnelController: NetworkProtection.TunnelControlle case .setConnectOnLogin, .setRegistrationKeyValidity, .setSelectedServer, - .setSelectedEnvironment: - // Intentional no-op as this is handled by the extension + .setSelectedEnvironment, + .setShowInMenuBar: + // Intentional no-op as this is handled by the extension or the agent's app delegate break } } diff --git a/DuckDuckGo/Preferences/Model/PreferencesSection.swift b/DuckDuckGo/Preferences/Model/PreferencesSection.swift index 11c71d25f8..036a23c8de 100644 --- a/DuckDuckGo/Preferences/Model/PreferencesSection.swift +++ b/DuckDuckGo/Preferences/Model/PreferencesSection.swift @@ -27,7 +27,7 @@ struct PreferencesSection: Hashable, Identifiable { static func defaultSections(includingDuckPlayer: Bool) -> [PreferencesSection] { let regularPanes: [PreferencePaneIdentifier] = { #if SUBSCRIPTION - var panes: [PreferencePaneIdentifier] = [.privacy, .vpn, .subscription, .general, .appearance, .autofill, .downloads] + var panes: [PreferencePaneIdentifier] = [.privacy, .subscription, .general, .appearance, .autofill, .downloads] if NSApp.delegateTyped.internalUserDecider.isInternalUser { if let generalIndex = panes.firstIndex(of: .general) { @@ -35,7 +35,7 @@ struct PreferencesSection: Hashable, Identifiable { } } #else - var panes: [PreferencePaneIdentifier] = [.vpn, .general, .appearance, .privacy, .autofill, .downloads] + var panes: [PreferencePaneIdentifier] = [.general, .appearance, .privacy, .autofill, .downloads] if NSApp.delegateTyped.internalUserDecider.isInternalUser { panes.insert(.sync, at: 1) @@ -45,6 +45,8 @@ struct PreferencesSection: Hashable, Identifiable { panes.append(.duckPlayer) } + panes.append(.vpn) + return panes }() diff --git a/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift b/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift index fed96a1501..92930c6a1f 100644 --- a/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift +++ b/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift @@ -28,60 +28,25 @@ final class VPNPreferencesModel: ObservableObject { } } -/* - @Published - var isLoginDetectionEnabled: Bool { + @Published var excludeLocalNetworks: Bool { didSet { - privacySecurityPreferences.loginDetectionEnabled = isLoginDetectionEnabled + tunnelSettings.excludeLocalNetworks = excludeLocalNetworks } } - @Published - var isGPCEnabled: Bool { + @Published var showInMenuBar: Bool { didSet { - privacySecurityPreferences.gpcEnabled = isGPCEnabled + tunnelSettings.showInMenuBar = showInMenuBar } } - @Published var isAutoconsentEnabled: Bool { - didSet { - privacySecurityPreferences.autoconsentEnabled = isAutoconsentEnabled - } - } - - @MainActor - func presentManageFireproofSitesDialog() { - let fireproofDomainsWindowController = FireproofDomainsViewController.create().wrappedInWindowController() - - guard let fireproofDomainsWindow = fireproofDomainsWindowController.window, - let parentWindowController = WindowControllersManager.shared.lastKeyMainWindowController - else { - assertionFailure("Privacy Preferences: Failed to present FireproofDomainsViewController") - return - } - - parentWindowController.window?.beginSheet(fireproofDomainsWindow) - } - - @MainActor - func openURL(_ url: URL) { - WindowControllersManager.shared.show(url: url, newTab: true) - } - - init(privacySecurityPreferences: PrivacySecurityPreferences = .shared) { - self.privacySecurityPreferences = privacySecurityPreferences - isLoginDetectionEnabled = privacySecurityPreferences.loginDetectionEnabled - isGPCEnabled = privacySecurityPreferences.gpcEnabled - isAutoconsentEnabled = privacySecurityPreferences.autoconsentEnabled ?? false - } - - private let privacySecurityPreferences: PrivacySecurityPreferences*/ - private let tunnelSettings: TunnelSettings init(tunnelSettings: TunnelSettings = .init(defaults: .shared)) { self.tunnelSettings = tunnelSettings connectOnLogin = tunnelSettings.connectOnLogin + excludeLocalNetworks = tunnelSettings.excludeLocalNetworks + showInMenuBar = tunnelSettings.showInMenuBar } } diff --git a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift index 66661c236f..f330346e5c 100644 --- a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift +++ b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift @@ -39,7 +39,7 @@ extension Preferences { ToggleMenuItem(title: "Connect on Login", isOn: $model.connectOnLogin) TextMenuItemCaption(text: "Automatically connect to the VPN service when you login") - ToggleMenuItem(title: "Show VPN in menu bar", isOn: $model.isAutoconsentEnabled) + ToggleMenuItem(title: "Show VPN in menu bar", isOn: $model.showInMenuBar) TextMenuItemCaption(text: "Display VPN status in menu bar, next to the Wi-Fi and Battery") ToggleMenuItem(title: "Always ON", isOn: $model.isAutoconsentEnabled) @@ -52,7 +52,6 @@ extension Preferences { ToggleMenuItem(title: "Exclude Local Networks", isOn: $model.isAutoconsentEnabled) TextMenuItemCaption(text: "Let local traffic bypass the VPN and connect to devices on your local network, like a printer") - ToggleMenuItem(title: "Secure DNS", isOn: $model.isAutoconsentEnabled) .disabled(true) TextMenuItemCaption(text: "Prevents DNS leaks to your Internet service provider by routing DNS queries through the VPN tunnel to our own resolver. For your security, this feature cannot be disabled.") diff --git a/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift b/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift index df250b0e01..025bc4e7d9 100644 --- a/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift +++ b/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift @@ -58,6 +58,8 @@ final class DuckDuckGoVPNAppDelegate: NSObject, NSApplicationDelegate { private let appLauncher = AppLauncher() private let bouncer = NetworkProtectionBouncer() + private var cancellables = Set() + var networkExtensionBundleID: String { Bundle.main.networkExtensionBundleID } @@ -143,11 +145,13 @@ final class DuckDuckGoVPNAppDelegate: NSObject, NSApplicationDelegate { menuItems: menuItems) }() + @MainActor func applicationDidFinishLaunching(_ aNotification: Notification) { APIRequest.Headers.setUserAgent(UserAgent.duckDuckGoUserAgent()) os_log("DuckDuckGoVPN started", log: .networkProtectionLoginItemLog, type: .info) - networkProtectionMenu.show() + + setupMenuVisibility() bouncer.requireAuthTokenOrKillApp() @@ -180,6 +184,25 @@ final class DuckDuckGoVPNAppDelegate: NSObject, NSApplicationDelegate { } } } + + @MainActor + private func setupMenuVisibility() { + if tunnelSettings.showInMenuBar { + networkProtectionMenu.show() + } else { + networkProtectionMenu.hide() + } + + tunnelSettings.showInMenuBarPublisher.sink { [weak self] showInMenuBar in + Task { @MainActor in + if showInMenuBar { + self?.networkProtectionMenu.show() + } else { + self?.networkProtectionMenu.hide() + } + } + }.store(in: &cancellables) + } } extension NSApplication { From 7ee6bcdb598133d9308392203961dcdb40facda4 Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Mon, 13 Nov 2023 15:56:45 +0100 Subject: [PATCH 04/40] Improves localization, implements VPN uninstallation --- DuckDuckGo/Common/Localizables/UserText.swift | 65 +++++++++++++++++++ .../Model/VPNPreferencesModel.swift | 34 ++++++++++ .../Preferences/View/PreferencesVPNView.swift | 36 ++++++---- 3 files changed, 121 insertions(+), 14 deletions(-) diff --git a/DuckDuckGo/Common/Localizables/UserText.swift b/DuckDuckGo/Common/Localizables/UserText.swift index c04dbcd17d..1709957064 100644 --- a/DuckDuckGo/Common/Localizables/UserText.swift +++ b/DuckDuckGo/Common/Localizables/UserText.swift @@ -37,6 +37,7 @@ struct UserText { static let deleteBookmark = NSLocalizedString("delete-bookmark", value: "Delete Bookmark", comment: "Delete Bookmark button") static let removeFavorite = NSLocalizedString("remove-favorite", value: "Remove Favorite", comment: "Remove Favorite button") static let quit = NSLocalizedString("quit", value: "Quit", comment: "Quit button") + static let uninstall = NSLocalizedString("uninstall", value: "Uninstall", comment: "Uninstall button") static let dontQuit = NSLocalizedString("dont.quit", value: "Don’t Quit", comment: "Don’t Quit button") static let next = NSLocalizedString("next", value: "Next", comment: "Next button") static let pasteAndGo = NSLocalizedString("paste.and.go", value: "Paste & Go", comment: "Paste & Go button") @@ -299,8 +300,72 @@ struct UserText { static let autoconsentCheckboxTitle = NSLocalizedString("autoconsent.checkbox.title", value: "Automatically handle cookie pop-ups", comment: "Autoconsent settings checkbox title") static let autoconsentExplanation = NSLocalizedString("autoconsent.explanation", value: "DuckDuckGo will try to select the most private settings available and hide these pop-ups for you.", comment: "Autoconsent feature explanation in settings") + // VPN Setting Titles + static let manageVPNSettingsTitle = NSLocalizedString("manage.vpn.settings.title", value: "Manage VPN", comment: "Manage VPN section title in VPN settings") static let vpnNotificationsSettingsTitle = NSLocalizedString("vpn.notifications.settings.title", value: "VPN Notifications", comment: "VPN Notifications section title in VPN settings") + static let vpnAdvancedSettingsTitle = NSLocalizedString("vpn.advanced.settings.title", value: "Advanced Settings", comment: "VPN Advanced section title in VPN settings") + + // VPN Settings + + static let vpnConnectOnLoginSettingTitle = NSLocalizedString( + "vpn.setting.title.connect.on.login", + value: "Connect on Login", + comment: "Connect on Login setting title") + static let vpnConnectOnLoginSettingDescription = NSLocalizedString( + "vpn.setting.description.connect.on.login", + value: "Automatically connect to the VPN service when you login", + comment: "Connect on Login setting description") + static let vpnShowInMenuBarSettingTitle = NSLocalizedString( + "vpn.setting.title.connect.on.login", + value: "Show VPN in menu bar", + comment: "Show VPN in menu bar setting title") + static let vpnShowInMenuBarSettingDescription = NSLocalizedString( + "vpn.setting.description.connect.on.login", + value: "Display VPN status in menu bar, next to the Wi-Fi and Battery", + comment: "Show VPN in menu bar setting description") + static let vpnAlwaysONSettingTitle = NSLocalizedString( + "vpn.setting.title.always.on", + value: "Always ON", + comment: "Always ON setting title") + static let vpnAlwaysOnSettingDescription = NSLocalizedString( + "vpn.setting.description.always.on", + value: "Display VPN status in menu bar, next to the Wi-Fi and Battery", + comment: "Always ON setting description") + static let vpnExcludeLocalNetworksSettingTitle = NSLocalizedString( + "vpn.setting.title.exclude.local.networks", + value: "Exclude Local Networks", + comment: "Exclude Local Networks setting title") + static let vpnExcludeLocalNetworksSettingDescription = NSLocalizedString( + "vpn.setting.description.exclude.local.networks", + value: "Let local traffic bypass the VPN and connect to devices on your local network, like a printer", + comment: "Exclude Local Networks setting description") + static let vpnSecureDNSSettingTitle = NSLocalizedString( + "vpn.setting.title.secure.dns", + value: "Secure DNS", + comment: "Secure DNS setting title") + static let vpnSecureDNSSettingDescription = NSLocalizedString( + "vpn.setting.description.secure.dns", + value: "Prevents DNS leaks to your Internet service provider by routing DNS queries through the VPN tunnel to our own resolver. For your security, this feature cannot be disabled.", + comment: "Secure DNS setting description") + static let vpnStatusChangeNotificationSettingTitle = NSLocalizedString( + "vpn.setting.title.status.change.notification", + value: "Get notified if your connection drops or VPN status changes", + comment: "Status Change Notification setting title") + static let uninstallVPNButtonTitle = NSLocalizedString( + "vpn.button.title.uninstall.vpn", + value: "Uninstall VPN", + comment: "Uninstall VPN button title") + + // VPN Settings Alerts + + static let uninstallVPNAlertTitle = NSLocalizedString("vpn.uninstall.alert.title", value: "Are you sure you want to uninstall our VPN?", comment: "Alert title when the user selects to uninstall our VPN") + static let uninstallVPNInformativeText = NSLocalizedString( + "vpn.uninstall.alert.informative.text", + value: "Uninstalling our VPN will remove it from your system and disconnect any active VPN connections.", + comment: "Informative text for the alert that comes up when the user decides to uninstall our VPN") + + // Misc static let duckPlayerSettingsTitle = NSLocalizedString("duck-player.title", value: "Duck Player", comment: "Private YouTube Player settings title") static let duckPlayerAlwaysOpenInPlayer = NSLocalizedString("duck-player.always-open-in-player", value: "Always open YouTube videos in Duck Player", comment: "Private YouTube Player option") diff --git a/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift b/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift index 92930c6a1f..f5f5e4a216 100644 --- a/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift +++ b/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift @@ -18,6 +18,7 @@ import Foundation import NetworkProtection +import AppKit final class VPNPreferencesModel: ObservableObject { @Published var isAutoconsentEnabled: Bool = true @@ -49,4 +50,37 @@ final class VPNPreferencesModel: ObservableObject { excludeLocalNetworks = tunnelSettings.excludeLocalNetworks showInMenuBar = tunnelSettings.showInMenuBar } + + func uninstallVPN() { + Task { @MainActor in + let response = await uninstallVPNConfirmationAlert().runModal() + + switch response { + case .OK: + NetworkProtectionFeatureDisabler().disable(keepAuthToken: true, uninstallSystemExtension: true) + case .cancel: + // intentional no-op + break + default: + // intentional no-op + break + } + } + } + + @MainActor + func uninstallVPNConfirmationAlert() -> NSAlert { + let alert = NSAlert() + alert.messageText = UserText.uninstallVPNAlertTitle + alert.informativeText = UserText.uninstallVPNInformativeText + let uninstallButton = alert.addButton(withTitle: UserText.uninstall) + uninstallButton.tag = NSApplication.ModalResponse.OK.rawValue + uninstallButton.keyEquivalent = "" + + let cancelButton = alert.addButton(withTitle: UserText.cancel) + cancelButton.tag = NSApplication.ModalResponse.cancel.rawValue + cancelButton.keyEquivalent = "\r" + + return alert + } } diff --git a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift index f330346e5c..b78722710c 100644 --- a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift +++ b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift @@ -36,25 +36,22 @@ extension Preferences { PreferencePaneSection { TextMenuItemHeader(text: UserText.manageVPNSettingsTitle) - ToggleMenuItem(title: "Connect on Login", isOn: $model.connectOnLogin) - TextMenuItemCaption(text: "Automatically connect to the VPN service when you login") + ToggleMenuItem(title: UserText.vpnConnectOnLoginSettingTitle, isOn: $model.connectOnLogin) + TextMenuItemCaption(text: UserText.vpnConnectOnLoginSettingDescription) - ToggleMenuItem(title: "Show VPN in menu bar", isOn: $model.showInMenuBar) - TextMenuItemCaption(text: "Display VPN status in menu bar, next to the Wi-Fi and Battery") + ToggleMenuItem(title: UserText.vpnShowInMenuBarSettingTitle, isOn: $model.showInMenuBar) + TextMenuItemCaption(text: UserText.vpnShowInMenuBarSettingDescription) - ToggleMenuItem(title: "Always ON", isOn: $model.isAutoconsentEnabled) + ToggleMenuItem(title: UserText.vpnAlwaysONSettingTitle, isOn: $model.isAutoconsentEnabled) .disabled(true) - TextMenuItemCaption(text: "Display VPN status in menu bar, next to the Wi-Fi and Battery") + TextMenuItemCaption(text: UserText.vpnAlwaysOnSettingDescription) - //ToggleMenuItem(title: "Killswitch", isOn: $model.isAutoconsentEnabled) - //TextMenuItemCaption(text: "Display VPN status in menu bar, next to the Wi-Fi and Battery") + ToggleMenuItem(title: UserText.vpnExcludeLocalNetworksSettingTitle, isOn: $model.excludeLocalNetworks) + TextMenuItemCaption(text: UserText.vpnExcludeLocalNetworksSettingDescription) - ToggleMenuItem(title: "Exclude Local Networks", isOn: $model.isAutoconsentEnabled) - TextMenuItemCaption(text: "Let local traffic bypass the VPN and connect to devices on your local network, like a printer") - - ToggleMenuItem(title: "Secure DNS", isOn: $model.isAutoconsentEnabled) + ToggleMenuItem(title: UserText.vpnSecureDNSSettingTitle, isOn: $model.isAutoconsentEnabled) .disabled(true) - TextMenuItemCaption(text: "Prevents DNS leaks to your Internet service provider by routing DNS queries through the VPN tunnel to our own resolver. For your security, this feature cannot be disabled.") + TextMenuItemCaption(text: UserText.vpnSecureDNSSettingDescription) } // SECTION: VPN Notifications @@ -62,7 +59,18 @@ extension Preferences { PreferencePaneSection { TextMenuItemHeader(text: UserText.vpnNotificationsSettingsTitle) - ToggleMenuItem(title: "Get notified if your connection drops or VPN status changes", isOn: $model.isAutoconsentEnabled) + ToggleMenuItem(title: UserText.vpnStatusChangeNotificationSettingTitle, isOn: $model.isAutoconsentEnabled) + } + + // SECTION: Uninstall + + PreferencePaneSection { + TextMenuItemHeader(text: UserText.vpnAdvancedSettingsTitle) + + Button(UserText.uninstallVPNButtonTitle) { + model.uninstallVPN() + } + .buttonStyle(DestructiveActionButtonStyle(enabled: true)) } } } From 4d4df9be01e57f6bf12f68219de487f869b3440e Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Mon, 13 Nov 2023 16:32:09 +0100 Subject: [PATCH 05/40] Adds option to open App showing our vpn settings --- DuckDuckGo/Application/URLEventHandler.swift | 2 ++ .../Localizables/UserText+NetworkProtection.swift | 1 + .../AppLauncher.swift | 14 +++++++++++++- .../NetworkProtectionNavBarPopoverManager.swift | 4 ++++ DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift | 6 +++--- DuckDuckGoVPN/UserText.swift | 2 +- 6 files changed, 24 insertions(+), 5 deletions(-) diff --git a/DuckDuckGo/Application/URLEventHandler.swift b/DuckDuckGo/Application/URLEventHandler.swift index 3e2ea6eaa9..f777ec90cd 100644 --- a/DuckDuckGo/Application/URLEventHandler.swift +++ b/DuckDuckGo/Application/URLEventHandler.swift @@ -121,6 +121,8 @@ final class URLEventHandler { Task { await WindowControllersManager.shared.showNetworkProtectionStatus() } + case AppLaunchCommand.showSettings.launchURL: + WindowControllersManager.shared.showPreferencesTab(withSelectedPane: .vpn) default: return } diff --git a/DuckDuckGo/Common/Localizables/UserText+NetworkProtection.swift b/DuckDuckGo/Common/Localizables/UserText+NetworkProtection.swift index 517541bcd5..92bf286419 100644 --- a/DuckDuckGo/Common/Localizables/UserText+NetworkProtection.swift +++ b/DuckDuckGo/Common/Localizables/UserText+NetworkProtection.swift @@ -38,6 +38,7 @@ extension UserText { // MARK: - Navigation Bar Status View static let networkProtectionNavBarStatusViewShareFeedback = NSLocalizedString("network.protection.navbar.status.view.share.feedback", value: "Share Feedback...", comment: "Menu item for 'Share Feedback' in the Network Protection status view that's shown in the navigation bar") + static let networkProtectionNavBarStatusMenuVPNSettings = NSLocalizedString("network.protection.status.menu.vpn.settings", value: "VPN Settings...", comment: "The status menu 'VPN Settings' menu item") // MARK: - System Extension Installation Messages diff --git a/DuckDuckGo/NetworkProtection/AppAndExtensionAndAgentTargets/AppLauncher.swift b/DuckDuckGo/NetworkProtection/AppAndExtensionAndAgentTargets/AppLauncher.swift index 0bca1a08db..2f072731dd 100644 --- a/DuckDuckGo/NetworkProtection/AppAndExtensionAndAgentTargets/AppLauncher.swift +++ b/DuckDuckGo/NetworkProtection/AppAndExtensionAndAgentTargets/AppLauncher.swift @@ -31,6 +31,7 @@ extension AppLaunchCommand { case .justOpen: return "justOpen" case .shareFeedback: return "shareFeedback" case .showStatus: return "showStatus" + case .showSettings: return "showSettings" case .enableOnDemand: return "enableOnDemand" } } @@ -48,7 +49,7 @@ public final class AppLauncher: AppLaunching { public func launchApp(withCommand command: AppLaunchCommand) async { let configuration = NSWorkspace.OpenConfiguration() - configuration.allowsRunningApplicationSubstitution = false + configuration.allowsRunningApplicationSubstitution = command.allowsRunningApplicationSubstitution configuration.arguments = [command.rawValue] if command.hideApp { @@ -85,11 +86,22 @@ extension AppLaunchCommand { return "https://form.asana.com/?k=_wNLt6YcT5ILpQjDuW0Mxw&d=137249556945" case .showStatus: return "networkprotection://show-status" + case .showSettings: + return "networkprotection://show-settings" default: return nil } } + var allowsRunningApplicationSubstitution: Bool { + switch self { + case .showSettings: + return true + default: + return false + } + } + var helperAppPath: String? { switch self { case .startVPN: diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift index 4a66937ea2..1a42cca575 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift @@ -59,6 +59,10 @@ final class NetworkProtectionNavBarPopoverManager { ) let menuItems = [ + NetworkProtectionStatusView.Model.MenuItem(name: UserText.networkProtectionNavBarStatusMenuVPNSettings, action: { + let appLauncher = AppLauncher(appBundleURL: Bundle.main.bundleURL) + await appLauncher.launchApp(withCommand: .showSettings) + }), NetworkProtectionStatusView.Model.MenuItem( name: UserText.networkProtectionNavBarStatusViewShareFeedback, action: { diff --git a/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift b/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift index 025bc4e7d9..27cfd95183 100644 --- a/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift +++ b/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift @@ -125,11 +125,11 @@ final class DuckDuckGoVPNAppDelegate: NSObject, NSApplicationDelegate { #endif let menuItems = [ + StatusBarMenu.MenuItem(name: UserText.networkProtectionStatusMenuVPNSettings, action: { [weak self] in + await self?.appLauncher.launchApp(withCommand: .showSettings) + }), StatusBarMenu.MenuItem(name: UserText.networkProtectionStatusMenuShareFeedback, action: { [weak self] in await self?.appLauncher.launchApp(withCommand: .shareFeedback) - }), - StatusBarMenu.MenuItem(name: UserText.networkProtectionStatusMenuOpenDuckDuckGo, action: { [weak self] in - await self?.appLauncher.launchApp(withCommand: .justOpen) }) ] diff --git a/DuckDuckGoVPN/UserText.swift b/DuckDuckGoVPN/UserText.swift index 227f211608..050d601727 100644 --- a/DuckDuckGoVPN/UserText.swift +++ b/DuckDuckGoVPN/UserText.swift @@ -22,5 +22,5 @@ final class UserText { // MARK: - Status Menu static let networkProtectionStatusMenuShareFeedback = NSLocalizedString("network.protection.status.menu.share.feedback", value: "Share Feedback...", comment: "The status menu 'Share Feedback' menu item") - static let networkProtectionStatusMenuOpenDuckDuckGo = NSLocalizedString("network.protection.status.menu.open.duckduckgo", value: "Open DuckDuckGo...", comment: "The status menu 'Open DuckDuckGo' menu item") + static let networkProtectionStatusMenuVPNSettings = NSLocalizedString("network.protection.status.menu.vpn.settings", value: "VPN Settings...", comment: "The status menu 'VPN Settings' menu item") } From 1e13253ab910ddb5c624b676a30522b19d3b2110 Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Wed, 15 Nov 2023 14:02:41 +0100 Subject: [PATCH 06/40] Added a fix so that a new window will be opened if needed when trying to show a preferences tab --- .../Windows/View/WindowControllersManager.swift | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/DuckDuckGo/Windows/View/WindowControllersManager.swift b/DuckDuckGo/Windows/View/WindowControllersManager.swift index 2f7c530c3d..4d39a932be 100644 --- a/DuckDuckGo/Windows/View/WindowControllersManager.swift +++ b/DuckDuckGo/Windows/View/WindowControllersManager.swift @@ -186,7 +186,17 @@ extension WindowControllersManager { } func showTab(with content: Tab.TabContent) { - guard let windowController = self.mainWindowController else { return } + guard let windowController = self.mainWindowController else { + Task { + WindowsManager.openNewWindow() + + // Not proud of this ugly hack... ideally openNewWindow() should let us know when the window is ready + try? await Task.sleep(interval: 0.5) + showTab(with: content) + } + + return + } let viewController = windowController.mainViewController let tabCollectionViewModel = viewController.tabCollectionViewModel From 2a07527a7ba3381702c1355eb17f37f3abee8ae8 Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Wed, 15 Nov 2023 14:47:03 +0100 Subject: [PATCH 07/40] Implements notification settings --- .../NetworkProtectionTunnelController.swift | 1 + .../Preferences/Model/VPNPreferencesModel.swift | 12 +++++++++++- DuckDuckGo/Preferences/View/PreferencesVPNView.swift | 6 +++--- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift index 842c52ce02..32d5a53a40 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift @@ -163,6 +163,7 @@ final class NetworkProtectionTunnelController: NetworkProtection.TunnelControlle case .setExcludeLocalNetworks(let excludeLocalNetworks): try await handleSetExcludeLocalNetworks(excludeLocalNetworks) case .setConnectOnLogin, + .setNotifyStatusChanges, .setRegistrationKeyValidity, .setSelectedServer, .setSelectedEnvironment, diff --git a/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift b/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift index f5f5e4a216..879dcf7e40 100644 --- a/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift +++ b/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift @@ -21,7 +21,8 @@ import NetworkProtection import AppKit final class VPNPreferencesModel: ObservableObject { - @Published var isAutoconsentEnabled: Bool = true + + @Published var alwaysON = true @Published var connectOnLogin: Bool { didSet { @@ -35,12 +36,20 @@ final class VPNPreferencesModel: ObservableObject { } } + @Published var secureDNS: Bool = true + @Published var showInMenuBar: Bool { didSet { tunnelSettings.showInMenuBar = showInMenuBar } } + @Published var notifyStatusChanges: Bool { + didSet { + tunnelSettings.notifyStatusChanges = notifyStatusChanges + } + } + private let tunnelSettings: TunnelSettings init(tunnelSettings: TunnelSettings = .init(defaults: .shared)) { @@ -48,6 +57,7 @@ final class VPNPreferencesModel: ObservableObject { connectOnLogin = tunnelSettings.connectOnLogin excludeLocalNetworks = tunnelSettings.excludeLocalNetworks + notifyStatusChanges = tunnelSettings.notifyStatusChanges showInMenuBar = tunnelSettings.showInMenuBar } diff --git a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift index b78722710c..4b891a108c 100644 --- a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift +++ b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift @@ -42,14 +42,14 @@ extension Preferences { ToggleMenuItem(title: UserText.vpnShowInMenuBarSettingTitle, isOn: $model.showInMenuBar) TextMenuItemCaption(text: UserText.vpnShowInMenuBarSettingDescription) - ToggleMenuItem(title: UserText.vpnAlwaysONSettingTitle, isOn: $model.isAutoconsentEnabled) + ToggleMenuItem(title: UserText.vpnAlwaysONSettingTitle, isOn: $model.alwaysON) .disabled(true) TextMenuItemCaption(text: UserText.vpnAlwaysOnSettingDescription) ToggleMenuItem(title: UserText.vpnExcludeLocalNetworksSettingTitle, isOn: $model.excludeLocalNetworks) TextMenuItemCaption(text: UserText.vpnExcludeLocalNetworksSettingDescription) - ToggleMenuItem(title: UserText.vpnSecureDNSSettingTitle, isOn: $model.isAutoconsentEnabled) + ToggleMenuItem(title: UserText.vpnSecureDNSSettingTitle, isOn: $model.secureDNS) .disabled(true) TextMenuItemCaption(text: UserText.vpnSecureDNSSettingDescription) } @@ -59,7 +59,7 @@ extension Preferences { PreferencePaneSection { TextMenuItemHeader(text: UserText.vpnNotificationsSettingsTitle) - ToggleMenuItem(title: UserText.vpnStatusChangeNotificationSettingTitle, isOn: $model.isAutoconsentEnabled) + ToggleMenuItem(title: UserText.vpnStatusChangeNotificationSettingTitle, isOn: $model.notifyStatusChanges) } // SECTION: Uninstall From c73aa798831087e498b9ec0781de8545e50cb1ab Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Wed, 15 Nov 2023 16:19:23 +0100 Subject: [PATCH 08/40] Feature flagged the new VPN Settings tab --- .../UserText+NetworkProtection.swift | 1 + .../NetworkProtectionDebugMenu.swift | 25 +++++++++++ .../NetworkProtectionDebugUtilities.swift | 8 +++- ...etworkProtectionNavBarPopoverManager.swift | 40 +++++++++++------- .../NetworkProtectionTunnelController.swift | 3 +- .../Model/PreferencesSection.swift | 6 ++- .../Model/PreferencesSidebarModel.swift | 6 ++- .../View/PreferencesViewController.swift | 4 +- DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift | 41 +++++++++++++------ .../Menu/NetworkProtectionStatusBarMenu.swift | 2 +- .../NetworkProtectionPopover.swift | 4 +- .../NetworkProtectionStatusView.swift | 2 +- .../NetworkProtectionStatusViewModel.swift | 4 +- 13 files changed, 106 insertions(+), 40 deletions(-) diff --git a/DuckDuckGo/Common/Localizables/UserText+NetworkProtection.swift b/DuckDuckGo/Common/Localizables/UserText+NetworkProtection.swift index 0c2cb38812..51a5519987 100644 --- a/DuckDuckGo/Common/Localizables/UserText+NetworkProtection.swift +++ b/DuckDuckGo/Common/Localizables/UserText+NetworkProtection.swift @@ -38,6 +38,7 @@ extension UserText { // MARK: - Navigation Bar Status View static let networkProtectionNavBarStatusViewShareFeedback = NSLocalizedString("network.protection.navbar.status.view.share.feedback", value: "Share Feedback...", comment: "Menu item for 'Share Feedback' in the Network Protection status view that's shown in the navigation bar") + static let networkProtectionStatusMenuOpenDuckDuckGo = NSLocalizedString("network.protection.status.menu.open.duckduckgo", value: "Open DuckDuckGo...", comment: "The status menu 'Open DuckDuckGo' menu item") static let networkProtectionNavBarStatusMenuVPNSettings = NSLocalizedString("network.protection.status.menu.vpn.settings", value: "VPN Settings...", comment: "The status menu 'VPN Settings' menu item") // MARK: - System Extension Installation Messages diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift index 6ff1f39b81..031d700a65 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift @@ -37,6 +37,9 @@ final class NetworkProtectionDebugMenu: NSMenu { private let registrationKeyValidityMenu: NSMenu private let registrationKeyValidityAutomaticItem = NSMenuItem(title: "Automatic", action: #selector(NetworkProtectionDebugMenu.setRegistrationKeyValidity)) + private let resetToDefaults = NSMenuItem(title: "Reset Settings to defaults", action: #selector(NetworkProtectionDebugMenu.resetSettings)) + private let showVPNSettingsMenuItem = NSMenuItem(title: "Show in settings", action: #selector(NetworkProtectionDebugMenu.toggleShowVPNSettings)) + private let exclusionsMenu = NSMenu() private let shouldEnforceRoutesMenuItem = NSMenuItem(title: "Kill Switch (enforceRoutes)", action: #selector(NetworkProtectionDebugMenu.toggleEnforceRoutesAction)) @@ -74,6 +77,7 @@ final class NetworkProtectionDebugMenu: NSMenu { NSMenuItem(title: "Reset Remote Messages", action: #selector(NetworkProtectionDebugMenu.resetNetworkProtectionRemoteMessages)) .targetting(self) + NSMenuItem.separator() connectOnLogInMenuItem @@ -139,6 +143,17 @@ final class NetworkProtectionDebugMenu: NSMenu { NSMenuItem(title: "NetP Waitlist Feature Flag Overrides") .submenu(NetworkProtectionWaitlistFeatureFlagOverridesMenu()) + + NSMenuItem(title: "VPN Settings") { + resetToDefaults + .targetting(self) + + NSMenuItem.separator() + + showVPNSettingsMenuItem + .targetting(self) + } + NSMenuItem.separator() NSMenuItem(title: "Kill Switch (alternative approach)") { @@ -204,6 +219,10 @@ final class NetworkProtectionDebugMenu: NSMenu { } } + @objc func resetSettings(_ sender: Any?) { + settings.resetToDefaults() + } + /// Removes the system extension and agents for Network Protection. /// @objc func removeSystemExtensionAndAgents(_ sender: Any?) { @@ -292,6 +311,10 @@ final class NetworkProtectionDebugMenu: NSMenu { NetworkProtectionTunnelController().setExcludedRoute(addressRange, enabled: sender.state == .off)*/ } + @objc func toggleShowVPNSettings(_ sender: NSMenuItem) { + settings.showVPNSettings.toggle() + } + @objc func openAppContainerInFinder(_ sender: Any?) { let containerURL = URL.sandboxApplicationSupportURL NSWorkspace.shared.selectFile(nil, inFileViewerRootedAtPath: containerURL.path) @@ -399,6 +422,8 @@ final class NetworkProtectionDebugMenu: NSMenu { updateRekeyValidityMenu() updateNetworkProtectionMenuItemsState() updateNetworkProtectionItems() + + showVPNSettingsMenuItem.state = settings.showVPNSettings ? .on : .off } private func updateEnvironmentMenu() { diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift index 5dca24962f..c1effb4f05 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift @@ -38,10 +38,15 @@ final class NetworkProtectionDebugUtilities { private let loginItemsManager: LoginItemsManager + // MARK: - Settings + + private let settings: TunnelSettings + // MARK: - Initializers - init(loginItemsManager: LoginItemsManager = .init()) { + init(loginItemsManager: LoginItemsManager = .init(), settings: TunnelSettings = .init(defaults: .shared)) { self.loginItemsManager = loginItemsManager + self.settings = settings let ipcClient = TunnelControllerIPCClient(machServiceName: Bundle.main.vpnMenuAgentBundleId) @@ -52,6 +57,7 @@ final class NetworkProtectionDebugUtilities { // MARK: - Debug commands for the extension func resetAllState(keepAuthToken: Bool) async throws { + settings.resetToDefaults() networkProtectionFeatureDisabler.disable(keepAuthToken: keepAuthToken, uninstallSystemExtension: true) NetworkProtectionWaitlist().waitlistStorage.deleteWaitlistState() diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift index 1a42cca575..15c06c918c 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift @@ -58,22 +58,32 @@ final class NetworkProtectionNavBarPopoverManager { controllerErrorMessageObserver: ControllerErrorMesssageObserverThroughDistributedNotifications() ) - let menuItems = [ - NetworkProtectionStatusView.Model.MenuItem(name: UserText.networkProtectionNavBarStatusMenuVPNSettings, action: { - let appLauncher = AppLauncher(appBundleURL: Bundle.main.bundleURL) - await appLauncher.launchApp(withCommand: .showSettings) - }), - NetworkProtectionStatusView.Model.MenuItem( - name: UserText.networkProtectionNavBarStatusViewShareFeedback, - action: { - let appLauncher = AppLauncher(appBundleURL: Bundle.main.bundleURL) - await appLauncher.launchApp(withCommand: .shareFeedback) - }) - ] - let onboardingStatusPublisher = UserDefaults.shared.networkProtectionOnboardingStatusPublisher - - let popover = NetworkProtectionPopover(controller: controller, onboardingStatusPublisher: onboardingStatusPublisher, statusReporter: statusReporter, menuItems: menuItems) + let tunnelSettings = TunnelSettings(defaults: .shared) + + let popover = NetworkProtectionPopover(controller: controller, onboardingStatusPublisher: onboardingStatusPublisher, statusReporter: statusReporter) { + + var menuItems = [ + NetworkProtectionStatusView.Model.MenuItem( + name: UserText.networkProtectionNavBarStatusViewShareFeedback, + action: { + let appLauncher = AppLauncher(appBundleURL: Bundle.main.bundleURL) + await appLauncher.launchApp(withCommand: .shareFeedback) + }) + ] + + if tunnelSettings.showVPNSettings { + menuItems.insert( + NetworkProtectionStatusView.Model.MenuItem( + name: UserText.networkProtectionNavBarStatusMenuVPNSettings, action: { + let appLauncher = AppLauncher(appBundleURL: Bundle.main.bundleURL) + await appLauncher.launchApp(withCommand: .showSettings) + }), + at: 0) + } + + return menuItems + } popover.delegate = delegate networkProtectionPopover = popover diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift index 32d5a53a40..2631dfa228 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift @@ -168,7 +168,8 @@ final class NetworkProtectionTunnelController: NetworkProtection.TunnelControlle .setSelectedServer, .setSelectedEnvironment, .setSelectedLocation, - .setShowInMenuBar: + .setShowInMenuBar, + .setShowVPNSettings: // Intentional no-op as this is handled by the extension or the agent's app delegate break } diff --git a/DuckDuckGo/Preferences/Model/PreferencesSection.swift b/DuckDuckGo/Preferences/Model/PreferencesSection.swift index d63d17c327..a87ef8f970 100644 --- a/DuckDuckGo/Preferences/Model/PreferencesSection.swift +++ b/DuckDuckGo/Preferences/Model/PreferencesSection.swift @@ -24,7 +24,7 @@ struct PreferencesSection: Hashable, Identifiable { let panes: [PreferencePaneIdentifier] @MainActor - static func defaultSections(includingDuckPlayer: Bool) -> [PreferencesSection] { + static func defaultSections(includingDuckPlayer: Bool, includingVPNSettings: Bool) -> [PreferencesSection] { let regularPanes: [PreferencePaneIdentifier] = { #if SUBSCRIPTION var panes: [PreferencePaneIdentifier] = [.privacy, .subscription, .general, .appearance, .autofill, .downloads] @@ -45,7 +45,9 @@ struct PreferencesSection: Hashable, Identifiable { panes.append(.duckPlayer) } - panes.append(.vpn) + if includingVPNSettings { + panes.append(.vpn) + } return panes }() diff --git a/DuckDuckGo/Preferences/Model/PreferencesSidebarModel.swift b/DuckDuckGo/Preferences/Model/PreferencesSidebarModel.swift index f206797b00..a2d03d89b4 100644 --- a/DuckDuckGo/Preferences/Model/PreferencesSidebarModel.swift +++ b/DuckDuckGo/Preferences/Model/PreferencesSidebarModel.swift @@ -19,6 +19,7 @@ import SwiftUI import BrowserServicesKit import Combine +import NetworkProtection final class PreferencesSidebarModel: ObservableObject { @@ -54,9 +55,10 @@ final class PreferencesSidebarModel: ObservableObject { convenience init( tabSwitcherTabs: [Tab.TabContent] = Tab.TabContent.displayableTabTypes, privacyConfigurationManager: PrivacyConfigurationManaging = ContentBlocking.shared.privacyConfigurationManager, - includeDuckPlayer: Bool + includeDuckPlayer: Bool, + tunnelSettings: TunnelSettings ) { - self.init(loadSections: { PreferencesSection.defaultSections(includingDuckPlayer: includeDuckPlayer) }, + self.init(loadSections: { PreferencesSection.defaultSections(includingDuckPlayer: includeDuckPlayer, includingVPNSettings: tunnelSettings.showVPNSettings) }, tabSwitcherTabs: tabSwitcherTabs, privacyConfigurationManager: privacyConfigurationManager) } diff --git a/DuckDuckGo/Preferences/View/PreferencesViewController.swift b/DuckDuckGo/Preferences/View/PreferencesViewController.swift index f7920d8f60..a0d729ca41 100644 --- a/DuckDuckGo/Preferences/View/PreferencesViewController.swift +++ b/DuckDuckGo/Preferences/View/PreferencesViewController.swift @@ -19,12 +19,14 @@ import AppKit import SwiftUI import Combine +import NetworkProtection final class PreferencesViewController: NSViewController { weak var delegate: BrowserTabSelectionDelegate? - let model = PreferencesSidebarModel(includeDuckPlayer: DuckPlayer.shared.isAvailable) + let model = PreferencesSidebarModel(includeDuckPlayer: DuckPlayer.shared.isAvailable, + tunnelSettings: .init(defaults: .shared)) private var selectedTabIndexCancellable: AnyCancellable? private var selectedPreferencePaneCancellable: AnyCancellable? diff --git a/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift b/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift index 27cfd95183..6b6eff32e5 100644 --- a/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift +++ b/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift @@ -116,6 +116,11 @@ final class DuckDuckGoVPNAppDelegate: NSObject, NSApplicationDelegate { /// @MainActor private lazy var networkProtectionMenu: StatusBarMenu = { + makeStatusBarMenu() + }() + + @MainActor + private func makeStatusBarMenu() -> StatusBarMenu { #if DEBUG let iconProvider = DebugMenuIconProvider() #elseif REVIEW @@ -124,26 +129,38 @@ final class DuckDuckGoVPNAppDelegate: NSObject, NSApplicationDelegate { let iconProvider = MenuIconProvider() #endif - let menuItems = [ - StatusBarMenu.MenuItem(name: UserText.networkProtectionStatusMenuVPNSettings, action: { [weak self] in - await self?.appLauncher.launchApp(withCommand: .showSettings) - }), - StatusBarMenu.MenuItem(name: UserText.networkProtectionStatusMenuShareFeedback, action: { [weak self] in - await self?.appLauncher.launchApp(withCommand: .shareFeedback) - }) - ] - let onboardingStatusPublisher = UserDefaults.shared.publisher(for: \.networkProtectionOnboardingStatusRawValue).map { rawValue in OnboardingStatus(rawValue: rawValue) ?? .default }.eraseToAnyPublisher() + let tunnelSettings = self.tunnelSettings + return StatusBarMenu( onboardingStatusPublisher: onboardingStatusPublisher, statusReporter: statusReporter, controller: tunnelController, - iconProvider: iconProvider, - menuItems: menuItems) - }() + iconProvider: iconProvider) { + if tunnelSettings.showVPNSettings { + return [ + StatusBarMenu.MenuItem(name: UserText.networkProtectionStatusMenuVPNSettings, action: { [weak self] in + await self?.appLauncher.launchApp(withCommand: .showSettings) + }), + StatusBarMenu.MenuItem(name: UserText.networkProtectionStatusMenuShareFeedback, action: { [weak self] in + await self?.appLauncher.launchApp(withCommand: .shareFeedback) + }) + ] + } else { + return [ + StatusBarMenu.MenuItem(name: UserText.networkProtectionStatusMenuShareFeedback, action: { [weak self] in + await self?.appLauncher.launchApp(withCommand: .shareFeedback) + }), + StatusBarMenu.MenuItem(name: UserText.networkProtectionStatusMenuOpenDuckDuckGo, action: { [weak self] in + await self?.appLauncher.launchApp(withCommand: .justOpen) + }) + ] + } + } + } @MainActor func applicationDidFinishLaunching(_ aNotification: Notification) { diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Menu/NetworkProtectionStatusBarMenu.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Menu/NetworkProtectionStatusBarMenu.swift index c7fe0059cc..890d1bee8f 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Menu/NetworkProtectionStatusBarMenu.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Menu/NetworkProtectionStatusBarMenu.swift @@ -48,7 +48,7 @@ public final class StatusBarMenu { statusReporter: NetworkProtectionStatusReporter, controller: TunnelController, iconProvider: IconProvider, - menuItems: [MenuItem]) { + menuItems: @escaping () -> [MenuItem]) { self.statusItem = statusItem ?? NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) self.iconPublisher = NetworkProtectionIconPublisher(statusReporter: statusReporter, iconProvider: iconProvider) diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/NetworkProtectionPopover.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/NetworkProtectionPopover.swift index 47f25e7192..a4668c3484 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/NetworkProtectionPopover.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/NetworkProtectionPopover.swift @@ -48,7 +48,7 @@ public final class NetworkProtectionPopover: NSPopover { public required init(controller: TunnelController, onboardingStatusPublisher: OnboardingStatusPublisher, statusReporter: NetworkProtectionStatusReporter, - menuItems: [MenuItem]) { + menuItems: @escaping () -> [MenuItem]) { self.statusReporter = statusReporter @@ -67,7 +67,7 @@ public final class NetworkProtectionPopover: NSPopover { private func setupContentController(controller: TunnelController, onboardingStatusPublisher: OnboardingStatusPublisher, statusReporter: NetworkProtectionStatusReporter, - menuItems: [MenuItem]) { + menuItems: @escaping () -> [MenuItem]) { let model = NetworkProtectionStatusView.Model(controller: controller, onboardingStatusPublisher: onboardingStatusPublisher, diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/StatusView/NetworkProtectionStatusView.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/StatusView/NetworkProtectionStatusView.swift index a138e4544c..ab6d1fcd26 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/StatusView/NetworkProtectionStatusView.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/StatusView/NetworkProtectionStatusView.swift @@ -97,7 +97,7 @@ public struct NetworkProtectionStatusView: View { private func bottomMenuView() -> some View { VStack(spacing: 0) { - ForEach(model.menuItems, id: \.name) { menuItem in + ForEach(model.menuItems(), id: \.name) { menuItem in MenuItemButton(menuItem.name, textColor: Color(.defaultText)) { await menuItem.action() dismiss() diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/StatusView/NetworkProtectionStatusViewModel.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/StatusView/NetworkProtectionStatusViewModel.swift index 3d7e8d489c..efef7ab117 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/StatusView/NetworkProtectionStatusViewModel.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/StatusView/NetworkProtectionStatusViewModel.swift @@ -68,7 +68,7 @@ extension NetworkProtectionStatusView { // MARK: - Extra Menu Items - public let menuItems: [MenuItem] + public let menuItems: () -> [MenuItem] // MARK: - Misc @@ -90,7 +90,7 @@ extension NetworkProtectionStatusView { public init(controller: TunnelController, onboardingStatusPublisher: OnboardingStatusPublisher, statusReporter: NetworkProtectionStatusReporter, - menuItems: [MenuItem], + menuItems: @escaping () -> [MenuItem], runLoopMode: RunLoop.Mode? = nil) { self.tunnelController = controller From 15635e52e023be700b4608f81bcfa892df480f6e Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Wed, 15 Nov 2023 18:26:36 +0100 Subject: [PATCH 09/40] Corrected the uninstall designs + copy --- DuckDuckGo/Common/Localizables/UserText.swift | 8 ++++---- DuckDuckGo/Preferences/View/PreferencesVPNView.swift | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/DuckDuckGo/Common/Localizables/UserText.swift b/DuckDuckGo/Common/Localizables/UserText.swift index 2c34d3bb13..b63b32db5e 100644 --- a/DuckDuckGo/Common/Localizables/UserText.swift +++ b/DuckDuckGo/Common/Localizables/UserText.swift @@ -304,7 +304,7 @@ struct UserText { static let manageVPNSettingsTitle = NSLocalizedString("manage.vpn.settings.title", value: "Manage VPN", comment: "Manage VPN section title in VPN settings") static let vpnNotificationsSettingsTitle = NSLocalizedString("vpn.notifications.settings.title", value: "VPN Notifications", comment: "VPN Notifications section title in VPN settings") - static let vpnAdvancedSettingsTitle = NSLocalizedString("vpn.advanced.settings.title", value: "Advanced Settings", comment: "VPN Advanced section title in VPN settings") + static let vpnAdvancedSettingsTitle = NSLocalizedString("vpn.advanced.settings.title", value: "Advanced", comment: "VPN Advanced section title in VPN settings") // VPN Settings @@ -354,15 +354,15 @@ struct UserText { comment: "Status Change Notification setting title") static let uninstallVPNButtonTitle = NSLocalizedString( "vpn.button.title.uninstall.vpn", - value: "Uninstall VPN", + value: "Uninstall DuckDuckGo VPN...", comment: "Uninstall VPN button title") // VPN Settings Alerts - static let uninstallVPNAlertTitle = NSLocalizedString("vpn.uninstall.alert.title", value: "Are you sure you want to uninstall our VPN?", comment: "Alert title when the user selects to uninstall our VPN") + static let uninstallVPNAlertTitle = NSLocalizedString("vpn.uninstall.alert.title", value: "Are you sure you want to uninstall the VPN?", comment: "Alert title when the user selects to uninstall our VPN") static let uninstallVPNInformativeText = NSLocalizedString( "vpn.uninstall.alert.informative.text", - value: "Uninstalling our VPN will remove it from your system and disconnect any active VPN connections.", + value: "Uninstalling the DuckDuckGo VPN will disconnect any active VPN connections and remove it from your device.", comment: "Informative text for the alert that comes up when the user decides to uninstall our VPN") // Misc diff --git a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift index 4b891a108c..7e7bcd7b78 100644 --- a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift +++ b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift @@ -70,7 +70,6 @@ extension Preferences { Button(UserText.uninstallVPNButtonTitle) { model.uninstallVPN() } - .buttonStyle(DestructiveActionButtonStyle(enabled: true)) } } } From b1f1b403e6077d5f69339cbdc41f00c1995d1ee4 Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Wed, 15 Nov 2023 18:32:27 +0100 Subject: [PATCH 10/40] Updates BSK --- DuckDuckGo.xcodeproj/project.pbxproj | 6 ++---- .../xcshareddata/swiftpm/Package.resolved | 8 ++++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index ba4461a9b5..22bd9480e3 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -4336,7 +4336,6 @@ 56D145F029E6F06D00E3488A /* MockBookmarkManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockBookmarkManager.swift; sourceTree = ""; }; 56D6A3D529DB2BAB0055215A /* ContinueSetUpView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContinueSetUpView.swift; sourceTree = ""; }; 7B05829D2A812AC000AC3F7C /* NetworkProtectionOnboardingMenu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkProtectionOnboardingMenu.swift; sourceTree = ""; }; - 7B1631052AFE534600B21188 /* BrowserServicesKit */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = BrowserServicesKit; path = ../../BrowserServicesKit; sourceTree = ""; }; 7B1E819B27C8874900FF0E60 /* ContentOverlayPopover.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentOverlayPopover.swift; sourceTree = ""; }; 7B1E819C27C8874900FF0E60 /* ContentOverlay.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = ContentOverlay.storyboard; sourceTree = ""; }; 7B1E819D27C8874900FF0E60 /* ContentOverlayViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentOverlayViewController.swift; sourceTree = ""; }; @@ -5591,7 +5590,6 @@ 378E279C2970217400FCADA2 /* LocalPackages */ = { isa = PBXGroup; children = ( - 7B1631052AFE534600B21188 /* BrowserServicesKit */, 1E862A852A9FBD7000F84D4B /* Account */, 378E279D2970217400FCADA2 /* BuildToolPlugins */, 3192A2702A4C4E330084EA89 /* DataBrokerProtection */, @@ -14458,8 +14456,8 @@ isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit"; requirement = { - kind = exactVersion; - version = 84.0.1; + kind = revision; + revision = 31b29ea56398381adda805be4d787e931df66c57; }; }; AA06B6B52672AF8100F541C5 /* XCRemoteSwiftPackageReference "Sparkle" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 9e35eae6af..d31171fe00 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -9,6 +9,14 @@ "version" : "3.0.0" } }, + { + "identity" : "browserserviceskit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/duckduckgo/BrowserServicesKit", + "state" : { + "revision" : "31b29ea56398381adda805be4d787e931df66c57" + } + }, { "identity" : "content-scope-scripts", "kind" : "remoteSourceControl", From eea3f2ad860625ad524e929981bc5b2c32a339fa Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Wed, 15 Nov 2023 18:58:19 +0100 Subject: [PATCH 11/40] Updates BSK --- DuckDuckGo.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 22bd9480e3..3cc331af66 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -14457,7 +14457,7 @@ repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit"; requirement = { kind = revision; - revision = 31b29ea56398381adda805be4d787e931df66c57; + revision = d1784c9240204ece3349e8cd65b621876653c4d0; }; }; AA06B6B52672AF8100F541C5 /* XCRemoteSwiftPackageReference "Sparkle" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index d31171fe00..0086c37d06 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -14,7 +14,7 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/duckduckgo/BrowserServicesKit", "state" : { - "revision" : "31b29ea56398381adda805be4d787e931df66c57" + "revision" : "d1784c9240204ece3349e8cd65b621876653c4d0" } }, { From 18e801400514020792f2a6db037435e7302cf992 Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Wed, 15 Nov 2023 19:01:05 +0100 Subject: [PATCH 12/40] Fixes swiftlint violations --- .../Preferences/View/PreferencesVPNView.swift | 2 +- .../LoginItemLaunchInformation.swift | 18 +++++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift index 7e7bcd7b78..7a15df0884 100644 --- a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift +++ b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift @@ -30,7 +30,7 @@ extension Preferences { // TITLE TextMenuTitle(text: UserText.vpn) - + // SECTION: Manage VPN PreferencePaneSection { diff --git a/LocalPackages/LoginItems/Sources/LoginItems/LoginItemLaunchInformation.swift b/LocalPackages/LoginItems/Sources/LoginItems/LoginItemLaunchInformation.swift index a9d30e60f2..f6e559f430 100644 --- a/LocalPackages/LoginItems/Sources/LoginItems/LoginItemLaunchInformation.swift +++ b/LocalPackages/LoginItems/Sources/LoginItems/LoginItemLaunchInformation.swift @@ -1,12 +1,24 @@ // -// File.swift -// +// LoginItemLaunchInformation.swift // -// Created by ddg on 10/11/23. +// Copyright © 2023 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // import Foundation import AppKit +// swiftlint:disable:next enforce_os_log_wrapper import os.log public struct LoginItemLaunchInformation: Equatable, Hashable { From f6d049a5dea62f9be5e8864fc60370b5401e7485 Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Wed, 15 Nov 2023 19:17:30 +0100 Subject: [PATCH 13/40] Corrects a mistake --- DuckDuckGo/Common/Localizables/UserText+NetworkProtection.swift | 1 - DuckDuckGoVPN/UserText.swift | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/DuckDuckGo/Common/Localizables/UserText+NetworkProtection.swift b/DuckDuckGo/Common/Localizables/UserText+NetworkProtection.swift index 51a5519987..0c2cb38812 100644 --- a/DuckDuckGo/Common/Localizables/UserText+NetworkProtection.swift +++ b/DuckDuckGo/Common/Localizables/UserText+NetworkProtection.swift @@ -38,7 +38,6 @@ extension UserText { // MARK: - Navigation Bar Status View static let networkProtectionNavBarStatusViewShareFeedback = NSLocalizedString("network.protection.navbar.status.view.share.feedback", value: "Share Feedback...", comment: "Menu item for 'Share Feedback' in the Network Protection status view that's shown in the navigation bar") - static let networkProtectionStatusMenuOpenDuckDuckGo = NSLocalizedString("network.protection.status.menu.open.duckduckgo", value: "Open DuckDuckGo...", comment: "The status menu 'Open DuckDuckGo' menu item") static let networkProtectionNavBarStatusMenuVPNSettings = NSLocalizedString("network.protection.status.menu.vpn.settings", value: "VPN Settings...", comment: "The status menu 'VPN Settings' menu item") // MARK: - System Extension Installation Messages diff --git a/DuckDuckGoVPN/UserText.swift b/DuckDuckGoVPN/UserText.swift index 050d601727..1ebb96993f 100644 --- a/DuckDuckGoVPN/UserText.swift +++ b/DuckDuckGoVPN/UserText.swift @@ -22,5 +22,6 @@ final class UserText { // MARK: - Status Menu static let networkProtectionStatusMenuShareFeedback = NSLocalizedString("network.protection.status.menu.share.feedback", value: "Share Feedback...", comment: "The status menu 'Share Feedback' menu item") + static let networkProtectionStatusMenuOpenDuckDuckGo = NSLocalizedString("network.protection.status.menu.open.duckduckgo", value: "Open DuckDuckGo...", comment: "The status menu 'Open DuckDuckGo' menu item") static let networkProtectionStatusMenuVPNSettings = NSLocalizedString("network.protection.status.menu.vpn.settings", value: "VPN Settings...", comment: "The status menu 'VPN Settings' menu item") } From 538bec950168a3d1397b5afd87749c6b92fa6eda Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Thu, 16 Nov 2023 12:12:52 +0100 Subject: [PATCH 14/40] Renames TunnelSettings to VPNSettings. Cross platform improvements for NetP --- DuckDuckGo.xcodeproj/project.pbxproj | 10 +++- .../xcshareddata/swiftpm/Package.resolved | 8 ---- ...rkProtection+ConvenienceInitializers.swift | 4 +- .../NetworkProtectionDebugMenu.swift | 6 +-- .../NetworkProtectionDebugUtilities.swift | 4 +- ...etworkProtectionNavBarPopoverManager.swift | 4 +- .../NetworkProtectionTunnelController.swift | 8 ++-- .../MacPacketTunnelProvider.swift | 28 ++++------- ...tectionNotificationsPresenterFactory.swift | 47 +++++++++++++++++++ .../Model/PreferencesSidebarModel.swift | 4 +- .../Model/VPNPreferencesModel.swift | 22 ++++----- .../View/PreferencesViewController.swift | 2 +- .../NetworkProtectionFeatureDisabler.swift | 4 +- DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift | 2 +- 14 files changed, 95 insertions(+), 58 deletions(-) create mode 100644 DuckDuckGo/NetworkProtection/NetworkExtensionTargets/NetworkExtensionTargets/NetworkProtectionNotificationsPresenterFactory.swift diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 3cc331af66..4ca3833c97 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -2975,6 +2975,8 @@ 7BF1A9DC2AE0551C00FCA683 /* DBPUnitTests.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 7BF1A9DB2AE0551C00FCA683 /* DBPUnitTests.xcconfig */; }; 7BFCB74E2ADE7E1A00DA3EA7 /* PixelKit in Frameworks */ = {isa = PBXBuildFile; productRef = 7BFCB74D2ADE7E1A00DA3EA7 /* PixelKit */; }; 7BFCB7502ADE7E2300DA3EA7 /* PixelKit in Frameworks */ = {isa = PBXBuildFile; productRef = 7BFCB74F2ADE7E2300DA3EA7 /* PixelKit */; }; + 7BFD0B7F2B06261F00727D35 /* NetworkProtectionNotificationsPresenterFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BFD0B7E2B06261F00727D35 /* NetworkProtectionNotificationsPresenterFactory.swift */; }; + 7BFD0B802B06261F00727D35 /* NetworkProtectionNotificationsPresenterFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BFD0B7E2B06261F00727D35 /* NetworkProtectionNotificationsPresenterFactory.swift */; }; 7BFE95522A9DF1CE0081ABE9 /* NetworkProtectionWaitlistFeatureFlagOverridesMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BFE95512A9DF1CE0081ABE9 /* NetworkProtectionWaitlistFeatureFlagOverridesMenu.swift */; }; 7BFE95542A9DF2930081ABE9 /* UserDefaults+NetworkProtectionWaitlist.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BFE95532A9DF2930081ABE9 /* UserDefaults+NetworkProtectionWaitlist.swift */; }; 7BFE95552A9DF2990081ABE9 /* UserDefaults+NetworkProtectionWaitlist.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BFE95532A9DF2930081ABE9 /* UserDefaults+NetworkProtectionWaitlist.swift */; }; @@ -4381,10 +4383,12 @@ 7BD1688D2AD4A4C400D24876 /* NetworkExtensionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkExtensionController.swift; sourceTree = ""; }; 7BD3AF5C2A8E7AF1006F9F56 /* KeychainType+ClientDefault.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "KeychainType+ClientDefault.swift"; sourceTree = ""; }; 7BD8679A2A9E9E000063B9F7 /* NetworkProtectionFeatureVisibility.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkProtectionFeatureVisibility.swift; sourceTree = ""; }; + 7BD952562B06236200BCCB7A /* BrowserServicesKit */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = BrowserServicesKit; path = ../../BrowserServicesKit; sourceTree = ""; }; 7BE146062A6A83C700C313B8 /* NetworkProtectionDebugMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionDebugMenu.swift; sourceTree = ""; }; 7BEC182D2AD5D89C00D30536 /* SystemExtensionManager */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = SystemExtensionManager; sourceTree = ""; }; 7BF1A9D72AE054D300FCA683 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 7BF1A9DB2AE0551C00FCA683 /* DBPUnitTests.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = DBPUnitTests.xcconfig; sourceTree = ""; }; + 7BFD0B7E2B06261F00727D35 /* NetworkProtectionNotificationsPresenterFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionNotificationsPresenterFactory.swift; sourceTree = ""; }; 7BFE95512A9DF1CE0081ABE9 /* NetworkProtectionWaitlistFeatureFlagOverridesMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionWaitlistFeatureFlagOverridesMenu.swift; sourceTree = ""; }; 7BFE95532A9DF2930081ABE9 /* UserDefaults+NetworkProtectionWaitlist.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UserDefaults+NetworkProtectionWaitlist.swift"; sourceTree = ""; }; 85012B0129133F9F003D0DCC /* NavigationBarPopovers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationBarPopovers.swift; sourceTree = ""; }; @@ -5590,6 +5594,7 @@ 378E279C2970217400FCADA2 /* LocalPackages */ = { isa = PBXGroup; children = ( + 7BD952562B06236200BCCB7A /* BrowserServicesKit */, 1E862A852A9FBD7000F84D4B /* Account */, 378E279D2970217400FCADA2 /* BuildToolPlugins */, 3192A2702A4C4E330084EA89 /* DataBrokerProtection */, @@ -5975,6 +5980,7 @@ isa = PBXGroup; children = ( EEF12E6D2A2111880023E6BF /* MacPacketTunnelProvider.swift */, + 7BFD0B7E2B06261F00727D35 /* NetworkProtectionNotificationsPresenterFactory.swift */, ); path = NetworkExtensionTargets; sourceTree = ""; @@ -11717,6 +11723,7 @@ 4BF0E50B2AD2552200FFEC9E /* NetworkProtectionPixelEvent.swift in Sources */, 4B2537782A11C00F00610219 /* NetworkProtectionExtensionMachService.swift in Sources */, B65DA5F32A77D3C700CBEE8D /* UserDefaultsWrapper.swift in Sources */, + 7BFD0B802B06261F00727D35 /* NetworkProtectionNotificationsPresenterFactory.swift in Sources */, 4B2537722A11BF8B00610219 /* main.swift in Sources */, EEF12E6F2A2111880023E6BF /* MacPacketTunnelProvider.swift in Sources */, 4B2D06292A11C0C900DE1F49 /* NetworkProtectionBundle.swift in Sources */, @@ -11819,6 +11826,7 @@ EEF12E6E2A2111880023E6BF /* MacPacketTunnelProvider.swift in Sources */, 4BF0E50C2AD2552300FFEC9E /* NetworkProtectionPixelEvent.swift in Sources */, 4B4D60AC2A0C804B00BCD287 /* OptionalExtension.swift in Sources */, + 7BFD0B7F2B06261F00727D35 /* NetworkProtectionNotificationsPresenterFactory.swift in Sources */, B6F92BA72A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */, B65DA5F22A77D3C600CBEE8D /* UserDefaultsWrapper.swift in Sources */, EEAD7A7A2A1D3E20002A24E7 /* AppLauncher.swift in Sources */, @@ -14457,7 +14465,7 @@ repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit"; requirement = { kind = revision; - revision = d1784c9240204ece3349e8cd65b621876653c4d0; + revision = 299e73ed6c9dc83f2b3935c4ba5d230cbb4e5489; }; }; AA06B6B52672AF8100F541C5 /* XCRemoteSwiftPackageReference "Sparkle" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 0086c37d06..9e35eae6af 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -9,14 +9,6 @@ "version" : "3.0.0" } }, - { - "identity" : "browserserviceskit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/duckduckgo/BrowserServicesKit", - "state" : { - "revision" : "d1784c9240204ece3349e8cd65b621876653c4d0" - } - }, { "identity" : "content-scope-scripts", "kind" : "remoteSourceControl", diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtection+ConvenienceInitializers.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtection+ConvenienceInitializers.swift index 261cbf4d87..ec449fa8ac 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtection+ConvenienceInitializers.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtection+ConvenienceInitializers.swift @@ -25,7 +25,7 @@ import Common extension NetworkProtectionDeviceManager { static func create() -> NetworkProtectionDeviceManager { - let settings = TunnelSettings(defaults: .shared) + let settings = VPNSettings(defaults: .shared) let keyStore = NetworkProtectionKeychainKeyStore() let tokenStore = NetworkProtectionKeychainTokenStore() return NetworkProtectionDeviceManager(environment: settings.selectedEnvironment, tokenStore: tokenStore, keyStore: keyStore, errorEvents: .networkProtectionAppDebugEvents) @@ -34,7 +34,7 @@ extension NetworkProtectionDeviceManager { extension NetworkProtectionCodeRedemptionCoordinator { convenience init() { - let settings = TunnelSettings(defaults: .shared) + let settings = VPNSettings(defaults: .shared) self.init(environment: settings.selectedEnvironment, tokenStore: NetworkProtectionKeychainTokenStore(), errorEvents: .networkProtectionAppDebugEvents) diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift index 031d700a65..a62d6c6c46 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift @@ -183,7 +183,7 @@ final class NetworkProtectionDebugMenu: NSMenu { // MARK: - Tunnel Settings - private let settings = TunnelSettings(defaults: .shared) + private let settings = VPNSettings(defaults: .shared) // MARK: - Debug Logic @@ -253,7 +253,7 @@ final class NetworkProtectionDebugMenu: NSMenu { /// @objc func setSelectedServer(_ menuItem: NSMenuItem) { let title = menuItem.title - let selectedServer: TunnelSettings.SelectedServer + let selectedServer: VPNSettings.SelectedServer if title == "Automatic" { selectedServer = .automatic @@ -589,7 +589,7 @@ final class NetworkProtectionDebugMenu: NSMenu { // MARK: Environment @objc func setSelectedEnvironment(_ menuItem: NSMenuItem) { let title = menuItem.title - let selectedEnvironment: TunnelSettings.SelectedEnvironment + let selectedEnvironment: VPNSettings.SelectedEnvironment if title == "Staging" { selectedEnvironment = .staging diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift index c1effb4f05..bbef6a2ec6 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift @@ -40,11 +40,11 @@ final class NetworkProtectionDebugUtilities { // MARK: - Settings - private let settings: TunnelSettings + private let settings: VPNSettings // MARK: - Initializers - init(loginItemsManager: LoginItemsManager = .init(), settings: TunnelSettings = .init(defaults: .shared)) { + init(loginItemsManager: LoginItemsManager = .init(), settings: VPNSettings = .init(defaults: .shared)) { self.loginItemsManager = loginItemsManager self.settings = settings diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift index 15c06c918c..2d0fb031c3 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift @@ -59,7 +59,7 @@ final class NetworkProtectionNavBarPopoverManager { ) let onboardingStatusPublisher = UserDefaults.shared.networkProtectionOnboardingStatusPublisher - let tunnelSettings = TunnelSettings(defaults: .shared) + let settings = VPNSettings(defaults: .shared) let popover = NetworkProtectionPopover(controller: controller, onboardingStatusPublisher: onboardingStatusPublisher, statusReporter: statusReporter) { @@ -72,7 +72,7 @@ final class NetworkProtectionNavBarPopoverManager { }) ] - if tunnelSettings.showVPNSettings { + if settings.showVPNSettings { menuItems.insert( NetworkProtectionStatusView.Model.MenuItem( name: UserText.networkProtectionNavBarStatusMenuVPNSettings, action: { diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift index 2631dfa228..5c98529bf5 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift @@ -35,7 +35,7 @@ typealias NetworkProtectionConfigChangeHandler = () -> Void final class NetworkProtectionTunnelController: NetworkProtection.TunnelController { - let settings: TunnelSettings + let settings: VPNSettings // MARK: - Combine Cancellables @@ -117,7 +117,7 @@ final class NetworkProtectionTunnelController: NetworkProtection.TunnelControlle /// init(networkExtensionBundleID: String, networkExtensionController: NetworkExtensionController, - settings: TunnelSettings, + settings: VPNSettings, notificationCenter: NotificationCenter = .default, tokenStore: NetworkProtectionTokenStore = NetworkProtectionKeychainTokenStore(), logger: NetworkProtectionLogger = DefaultNetworkProtectionLogger()) { @@ -154,7 +154,7 @@ final class NetworkProtectionTunnelController: NetworkProtection.TunnelControlle /// /// The extension can also handle these changes so not everything needs to be handled here. /// - private func handleSettingsChange(_ change: TunnelSettings.Change) async throws { + private func handleSettingsChange(_ change: VPNSettings.Change) async throws { switch change { case .setIncludeAllNetworks(let includeAllNetworks): try await handleSetIncludeAllNetworks(includeAllNetworks) @@ -203,7 +203,7 @@ final class NetworkProtectionTunnelController: NetworkProtection.TunnelControlle updateRoutes() } - private func relaySettingsChange(_ change: TunnelSettings.Change) async throws { + private func relaySettingsChange(_ change: VPNSettings.Change) async throws { guard await isConnected, let activeSession = try await ConnectionSessionUtilities.activeSession(networkExtensionBundleID: networkExtensionBundleID) else { return } diff --git a/DuckDuckGo/NetworkProtection/NetworkExtensionTargets/NetworkExtensionTargets/MacPacketTunnelProvider.swift b/DuckDuckGo/NetworkProtection/NetworkExtensionTargets/NetworkExtensionTargets/MacPacketTunnelProvider.swift index 9fadeafef0..9388585fde 100644 --- a/DuckDuckGo/NetworkProtection/NetworkExtensionTargets/NetworkExtensionTargets/MacPacketTunnelProvider.swift +++ b/DuckDuckGo/NetworkProtection/NetworkExtensionTargets/NetworkExtensionTargets/MacPacketTunnelProvider.swift @@ -37,23 +37,6 @@ final class MacPacketTunnelProvider: PacketTunnelProvider { private var cancellables = Set() - // MARK: - User Notifications - - private static func makeNotificationsPresenter() -> NetworkProtectionNotificationsPresenter { -#if NETP_SYSTEM_EXTENSION - return NetworkProtectionAgentNotificationsPresenter(notificationCenter: DistributedNotificationCenter.default()) -#else - let parentBundlePath = "../../../" - let mainAppURL: URL - if #available(macOS 13, *) { - mainAppURL = URL(filePath: parentBundlePath, relativeTo: Bundle.main.bundleURL) - } else { - mainAppURL = URL(fileURLWithPath: parentBundlePath, relativeTo: Bundle.main.bundleURL) - } - return NetworkProtectionUNNotificationsPresenter(appLauncher: AppLauncher(appBundleURL: mainAppURL)) -#endif - } - private let appLauncher: AppLaunching? // MARK: - Error Reporting @@ -181,20 +164,27 @@ final class MacPacketTunnelProvider: PacketTunnelProvider { @objc public init() { self.appLauncher = AppLauncher(appBundleURL: .mainAppBundleURL) +#if NETP_SYSTEM_EXTENSION + let settings = VPNSettings(defaults: .standard) +#else + let settings = VPNSettings(defaults: .shared) +#endif let tunnelHealthStore = NetworkProtectionTunnelHealthStore(notificationCenter: notificationCenter) let controllerErrorStore = NetworkProtectionTunnelErrorStore(notificationCenter: notificationCenter) let debugEvents = Self.networkProtectionDebugEvents(controllerErrorStore: controllerErrorStore) let tokenStore = NetworkProtectionKeychainTokenStore(keychainType: NetworkProtectionBundle.keychainType, serviceName: Self.tokenServiceName, errorEvents: debugEvents) + let notificationsPresenter = NetworkProtectionNotificationsPresenterFactory().make(settings: settings) - super.init(notificationsPresenter: Self.makeNotificationsPresenter(), + super.init(notificationsPresenter: notificationsPresenter, tunnelHealthStore: tunnelHealthStore, controllerErrorStore: controllerErrorStore, keychainType: NetworkProtectionBundle.keychainType, tokenStore: tokenStore, debugEvents: debugEvents, - providerEvents: Self.packetTunnelProviderEvents) + providerEvents: Self.packetTunnelProviderEvents, + settings: settings) observeConnectionStatusChanges() observeServerChanges() diff --git a/DuckDuckGo/NetworkProtection/NetworkExtensionTargets/NetworkExtensionTargets/NetworkProtectionNotificationsPresenterFactory.swift b/DuckDuckGo/NetworkProtection/NetworkExtensionTargets/NetworkExtensionTargets/NetworkProtectionNotificationsPresenterFactory.swift new file mode 100644 index 0000000000..23419c8918 --- /dev/null +++ b/DuckDuckGo/NetworkProtection/NetworkExtensionTargets/NetworkExtensionTargets/NetworkProtectionNotificationsPresenterFactory.swift @@ -0,0 +1,47 @@ +// +// NetworkProtectionNotificationsPresenterFactory.swift +// +// Copyright © 2023 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import NetworkProtection + +/// A convenience class for making notification presenters. +/// +struct NetworkProtectionNotificationsPresenterFactory { + func make(settings: VPNSettings) -> NetworkProtectionNotificationsPresenter { + let presenterForBuildType = makePresenterForBuildType() + + return NetworkProtectionNotificationsPresenterTogglableDecorator( + settings: settings, + wrappee: presenterForBuildType) + } + + private func makePresenterForBuildType() -> NetworkProtectionNotificationsPresenter { + #if NETP_SYSTEM_EXTENSION + return NetworkProtectionAgentNotificationsPresenter(notificationCenter: DistributedNotificationCenter.default()) + #else + let parentBundlePath = "../../../" + let mainAppURL: URL + if #available(macOS 13, *) { + mainAppURL = URL(filePath: parentBundlePath, relativeTo: Bundle.main.bundleURL) + } else { + mainAppURL = URL(fileURLWithPath: parentBundlePath, relativeTo: Bundle.main.bundleURL) + } + return NetworkProtectionUNNotificationsPresenter(appLauncher: AppLauncher(appBundleURL: mainAppURL)) + #endif + } +} diff --git a/DuckDuckGo/Preferences/Model/PreferencesSidebarModel.swift b/DuckDuckGo/Preferences/Model/PreferencesSidebarModel.swift index a2d03d89b4..d03b231c8f 100644 --- a/DuckDuckGo/Preferences/Model/PreferencesSidebarModel.swift +++ b/DuckDuckGo/Preferences/Model/PreferencesSidebarModel.swift @@ -56,9 +56,9 @@ final class PreferencesSidebarModel: ObservableObject { tabSwitcherTabs: [Tab.TabContent] = Tab.TabContent.displayableTabTypes, privacyConfigurationManager: PrivacyConfigurationManaging = ContentBlocking.shared.privacyConfigurationManager, includeDuckPlayer: Bool, - tunnelSettings: TunnelSettings + settings: VPNSettings ) { - self.init(loadSections: { PreferencesSection.defaultSections(includingDuckPlayer: includeDuckPlayer, includingVPNSettings: tunnelSettings.showVPNSettings) }, + self.init(loadSections: { PreferencesSection.defaultSections(includingDuckPlayer: includeDuckPlayer, includingVPNSettings: settings.showVPNSettings) }, tabSwitcherTabs: tabSwitcherTabs, privacyConfigurationManager: privacyConfigurationManager) } diff --git a/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift b/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift index 879dcf7e40..b12a211e24 100644 --- a/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift +++ b/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift @@ -26,13 +26,13 @@ final class VPNPreferencesModel: ObservableObject { @Published var connectOnLogin: Bool { didSet { - tunnelSettings.connectOnLogin = connectOnLogin + settings.connectOnLogin = connectOnLogin } } @Published var excludeLocalNetworks: Bool { didSet { - tunnelSettings.excludeLocalNetworks = excludeLocalNetworks + settings.excludeLocalNetworks = excludeLocalNetworks } } @@ -40,25 +40,25 @@ final class VPNPreferencesModel: ObservableObject { @Published var showInMenuBar: Bool { didSet { - tunnelSettings.showInMenuBar = showInMenuBar + settings.showInMenuBar = showInMenuBar } } @Published var notifyStatusChanges: Bool { didSet { - tunnelSettings.notifyStatusChanges = notifyStatusChanges + settings.notifyStatusChanges = notifyStatusChanges } } - private let tunnelSettings: TunnelSettings + private let settings: VPNSettings - init(tunnelSettings: TunnelSettings = .init(defaults: .shared)) { - self.tunnelSettings = tunnelSettings + init(settings: VPNSettings = .init(defaults: .shared)) { + self.settings = settings - connectOnLogin = tunnelSettings.connectOnLogin - excludeLocalNetworks = tunnelSettings.excludeLocalNetworks - notifyStatusChanges = tunnelSettings.notifyStatusChanges - showInMenuBar = tunnelSettings.showInMenuBar + connectOnLogin = settings.connectOnLogin + excludeLocalNetworks = settings.excludeLocalNetworks + notifyStatusChanges = settings.notifyStatusChanges + showInMenuBar = settings.showInMenuBar } func uninstallVPN() { diff --git a/DuckDuckGo/Preferences/View/PreferencesViewController.swift b/DuckDuckGo/Preferences/View/PreferencesViewController.swift index a0d729ca41..c94166e6c9 100644 --- a/DuckDuckGo/Preferences/View/PreferencesViewController.swift +++ b/DuckDuckGo/Preferences/View/PreferencesViewController.swift @@ -26,7 +26,7 @@ final class PreferencesViewController: NSViewController { weak var delegate: BrowserTabSelectionDelegate? let model = PreferencesSidebarModel(includeDuckPlayer: DuckPlayer.shared.isAvailable, - tunnelSettings: .init(defaults: .shared)) + settings: .init(defaults: .shared)) private var selectedTabIndexCancellable: AnyCancellable? private var selectedPreferencePaneCancellable: AnyCancellable? diff --git a/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift b/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift index 6458ed80e4..47dfa668e8 100644 --- a/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift +++ b/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift @@ -34,14 +34,14 @@ final class NetworkProtectionFeatureDisabler: NetworkProtectionFeatureDisabling private let log: OSLog private let loginItemsManager: LoginItemsManager private let pinningManager: LocalPinningManager - private let settings: TunnelSettings + private let settings: VPNSettings private let userDefaults: UserDefaults private let ipcClient: TunnelControllerIPCClient init(loginItemsManager: LoginItemsManager = LoginItemsManager(), pinningManager: LocalPinningManager = .shared, userDefaults: UserDefaults = .shared, - settings: TunnelSettings = .init(defaults: .shared), + settings: VPNSettings = .init(defaults: .shared), ipcClient: TunnelControllerIPCClient = TunnelControllerIPCClient(machServiceName: Bundle.main.vpnMenuAgentBundleId), log: OSLog = .networkProtection) { diff --git a/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift b/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift index 6b6eff32e5..339d135c33 100644 --- a/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift +++ b/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift @@ -68,7 +68,7 @@ final class DuckDuckGoVPNAppDelegate: NSObject, NSApplicationDelegate { private lazy var networkExtensionController = NetworkExtensionController(extensionBundleID: networkExtensionBundleID) #endif - private lazy var tunnelSettings = TunnelSettings(defaults: .shared) + private lazy var tunnelSettings = VPNSettings(defaults: .shared) private lazy var tunnelController = NetworkProtectionTunnelController( networkExtensionBundleID: networkExtensionBundleID, From 9ab40c951698c013a833b675efc84130748a08a8 Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Thu, 16 Nov 2023 15:30:38 +0100 Subject: [PATCH 15/40] Removes NetworkProtectionUserDefaultsConstants.swift --- DuckDuckGo.xcodeproj/project.pbxproj | 20 ------------ ...tworkProtectionUserDefaultsConstants.swift | 31 ------------------- 2 files changed, 51 deletions(-) delete mode 100644 DuckDuckGo/NetworkProtection/AppAndExtensionAndAgentTargets/NetworkProtectionUserDefaultsConstants.swift diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 4ca3833c97..32ecf98e11 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -114,7 +114,6 @@ 316C7A832A7E9BEE00AA3BAE /* BookmarksBarAppearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 850E8DFA2A6FEC5E00691187 /* BookmarksBarAppearance.swift */; }; 316C7A842A7E9C1700AA3BAE /* PixelExperiment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 857E5AF42A79045800FC0FB4 /* PixelExperiment.swift */; }; 316C7A852A7E9C2300AA3BAE /* BookmarksBarMenuFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85774AFE2A713D3B00DE0561 /* BookmarksBarMenuFactory.swift */; }; - 316C7A862A7E9C2F00AA3BAE /* NetworkProtectionUserDefaultsConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F92BA42A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift */; }; 316C7A872A7E9C3B00AA3BAE /* BlockMenuItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85774B022A71CDD000DE0561 /* BlockMenuItem.swift */; }; 316C7A882A7E9C4D00AA3BAE /* BookmarksBarPromptPopover.swift in Sources */ = {isa = PBXBuildFile; fileRef = 859F30632A72A7BB00C20372 /* BookmarksBarPromptPopover.swift */; }; 3171D6B82889849F0068632A /* CookieManagedNotificationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3171D6B72889849F0068632A /* CookieManagedNotificationView.swift */; }; @@ -2046,7 +2045,6 @@ 4B9579A32AC7AE700062CA31 /* PopUpButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BBE0AA627B9B027003B37A8 /* PopUpButton.swift */; }; 4B9579A42AC7AE700062CA31 /* NetworkProtectionInviteDialog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B4D606C2A0B29FA00BCD287 /* NetworkProtectionInviteDialog.swift */; }; 4B9579A52AC7AE700062CA31 /* SuggestionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AABEE6A424AA0A7F0043105B /* SuggestionViewController.swift */; }; - 4B9579A62AC7AE700062CA31 /* NetworkProtectionUserDefaultsConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F92BA42A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift */; }; 4B9579A72AC7AE700062CA31 /* AddEditFavoriteWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85589E7A27BBB8620038AD11 /* AddEditFavoriteWindow.swift */; }; 4B9579A82AC7AE700062CA31 /* BWKeyStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D6216B129069BBF00386B2C /* BWKeyStorage.swift */; }; 4B9579A92AC7AE700062CA31 /* VisitViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA7E919E287872EA00AB6B62 /* VisitViewModel.swift */; }; @@ -3659,13 +3657,6 @@ B6F7128229F6820A00594A45 /* QuickLookUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6F7128029F681EB00594A45 /* QuickLookUI.framework */; }; B6F92BA22A691580002ABA6B /* UserDefaultsWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85C6A29525CC1FFD00EEB5F1 /* UserDefaultsWrapper.swift */; }; B6F92BA32A691583002ABA6B /* UserDefaultsWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85C6A29525CC1FFD00EEB5F1 /* UserDefaultsWrapper.swift */; }; - B6F92BA52A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F92BA42A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift */; }; - B6F92BA62A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F92BA42A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift */; }; - B6F92BA72A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F92BA42A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift */; }; - B6F92BA82A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F92BA42A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift */; }; - B6F92BA92A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F92BA42A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift */; }; - B6F92BAA2A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F92BA42A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift */; }; - B6F92BAB2A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F92BA42A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift */; }; B6F92BAC2A6937B3002ABA6B /* OptionalExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = B637273C26CCF0C200C8CB02 /* OptionalExtension.swift */; }; B6F92BAD2A6937B5002ABA6B /* OptionalExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = B637273C26CCF0C200C8CB02 /* OptionalExtension.swift */; }; B6FA893D269C423100588ECD /* PrivacyDashboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B6FA893C269C423100588ECD /* PrivacyDashboard.storyboard */; }; @@ -4936,7 +4927,6 @@ B6F56566299A414300A04298 /* WKWebViewMockingExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WKWebViewMockingExtension.swift; sourceTree = ""; }; B6F7127D29F6779000594A45 /* QRSharingService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRSharingService.swift; sourceTree = ""; }; B6F7128029F681EB00594A45 /* QuickLookUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickLookUI.framework; path = System/Library/Frameworks/QuickLookUI.framework; sourceTree = SDKROOT; }; - B6F92BA42A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionUserDefaultsConstants.swift; sourceTree = ""; }; B6FA893C269C423100588ECD /* PrivacyDashboard.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = PrivacyDashboard.storyboard; sourceTree = ""; }; B6FA893E269C424500588ECD /* PrivacyDashboardViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacyDashboardViewController.swift; sourceTree = ""; }; B6FA8940269C425400588ECD /* PrivacyDashboardPopover.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacyDashboardPopover.swift; sourceTree = ""; }; @@ -8641,7 +8631,6 @@ children = ( EEAD7A6E2A1D3E1F002A24E7 /* AppLauncher.swift */, 4BF0E5042AD2551A00FFEC9E /* NetworkProtectionPixelEvent.swift */, - B6F92BA42A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift */, 7B934C402A866DD400FC8F9C /* UserDefaults+NetworkProtectionShared.swift */, 7BFE95532A9DF2930081ABE9 /* UserDefaults+NetworkProtectionWaitlist.swift */, ); @@ -10215,7 +10204,6 @@ 3192A0292A4C4CFF0084EA89 /* DownloadsPopover.swift in Sources */, 3192A02A2A4C4CFF0084EA89 /* SpacerNode.swift in Sources */, 4B9DB0252A983B24000927DB /* WaitlistRequest.swift in Sources */, - 316C7A862A7E9C2F00AA3BAE /* NetworkProtectionUserDefaultsConstants.swift in Sources */, 3192A02D2A4C4CFF0084EA89 /* SyncManagementDialogViewController.swift in Sources */, 3192A02E2A4C4CFF0084EA89 /* BookmarkExtension.swift in Sources */, 4B6785412AA7C726008A5004 /* DailyPixel.swift in Sources */, @@ -11224,7 +11212,6 @@ B60C6F7829B0E286007BFAA8 /* SearchNonexistentDomainNavigationResponder.swift in Sources */, 3707C720294B5D2900682A9F /* WKWebsiteDataStoreExtension.swift in Sources */, 3706FC03293F65D500E42796 /* TabPreviewViewController.swift in Sources */, - B6F92BA62A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */, 4B9754EC2984300100D7B834 /* EmailManagerExtension.swift in Sources */, 3706FC04293F65D500E42796 /* PreferencesPrivacyView.swift in Sources */, 3706FC05293F65D500E42796 /* NSPasteboardExtension.swift in Sources */, @@ -11713,7 +11700,6 @@ B65DA5F42A77D3FA00CBEE8D /* BundleExtension.swift in Sources */, 4B2D062D2A11C12300DE1F49 /* Logging.swift in Sources */, 7B2E52252A5FEC09000C6D39 /* NetworkProtectionAgentNotificationsPresenter.swift in Sources */, - B6F92BA82A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */, B602E8232A1E260E006D261F /* Bundle+NetworkProtectionExtensions.swift in Sources */, EEAD7A7B2A1D3E20002A24E7 /* AppLauncher.swift in Sources */, 4B2D062A2A11C0C900DE1F49 /* NetworkProtectionOptionKeyExtension.swift in Sources */, @@ -11751,7 +11737,6 @@ 7BA7CC4A2AD11EA00042E5CE /* NetworkProtectionTunnelController.swift in Sources */, 7BD1688E2AD4A4C400D24876 /* NetworkExtensionController.swift in Sources */, 7BA7CC3E2AD11E380042E5CE /* TunnelControllerIPCService.swift in Sources */, - B6F92BAA2A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */, 7BA7CC402AD11E3D0042E5CE /* AppLauncher+DefaultInitializer.swift in Sources */, EEC589DB2A4F1CE700BCD60C /* AppLauncher.swift in Sources */, B65DA5EF2A77CC3A00CBEE8D /* Bundle+NetworkProtectionExtensions.swift in Sources */, @@ -11771,7 +11756,6 @@ B6F92BA32A691583002ABA6B /* UserDefaultsWrapper.swift in Sources */, 4B2D067C2A13340900DE1F49 /* Logging.swift in Sources */, B6F92BAD2A6937B5002ABA6B /* OptionalExtension.swift in Sources */, - B6F92BAB2A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */, 7BA7CC5A2AD120640042E5CE /* NetworkProtection+ConvenienceInitializers.swift in Sources */, 7BA7CC3B2AD11E330042E5CE /* Bundle+Configuration.swift in Sources */, EEC589DC2A4F1CE800BCD60C /* AppLauncher.swift in Sources */, @@ -11806,7 +11790,6 @@ B602E8222A1E2603006D261F /* Bundle+NetworkProtectionExtensions.swift in Sources */, B602E81A2A1E2570006D261F /* URL+NetworkProtection.swift in Sources */, 4B4BEC402A11B5B5001D9AC5 /* NetworkProtectionExtensionMachService.swift in Sources */, - B6F92BA92A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */, EEAD7A7C2A1D3E20002A24E7 /* AppLauncher.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -11827,7 +11810,6 @@ 4BF0E50C2AD2552300FFEC9E /* NetworkProtectionPixelEvent.swift in Sources */, 4B4D60AC2A0C804B00BCD287 /* OptionalExtension.swift in Sources */, 7BFD0B7F2B06261F00727D35 /* NetworkProtectionNotificationsPresenterFactory.swift in Sources */, - B6F92BA72A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */, B65DA5F22A77D3C600CBEE8D /* UserDefaultsWrapper.swift in Sources */, EEAD7A7A2A1D3E20002A24E7 /* AppLauncher.swift in Sources */, ); @@ -11935,7 +11917,6 @@ 4B9579A32AC7AE700062CA31 /* PopUpButton.swift in Sources */, 4B9579A42AC7AE700062CA31 /* NetworkProtectionInviteDialog.swift in Sources */, 4B9579A52AC7AE700062CA31 /* SuggestionViewController.swift in Sources */, - 4B9579A62AC7AE700062CA31 /* NetworkProtectionUserDefaultsConstants.swift in Sources */, 4B9579A72AC7AE700062CA31 /* AddEditFavoriteWindow.swift in Sources */, 4B9579A82AC7AE700062CA31 /* BWKeyStorage.swift in Sources */, 4B9579A92AC7AE700062CA31 /* VisitViewModel.swift in Sources */, @@ -12656,7 +12637,6 @@ 4BBE0AA727B9B027003B37A8 /* PopUpButton.swift in Sources */, 4B4D60CF2A0C849600BCD287 /* NetworkProtectionInviteDialog.swift in Sources */, AABEE6A524AA0A7F0043105B /* SuggestionViewController.swift in Sources */, - B6F92BA52A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */, 85589E8027BBB8630038AD11 /* AddEditFavoriteWindow.swift in Sources */, 1D6216B229069BBF00386B2C /* BWKeyStorage.swift in Sources */, AA7E919F287872EA00AB6B62 /* VisitViewModel.swift in Sources */, diff --git a/DuckDuckGo/NetworkProtection/AppAndExtensionAndAgentTargets/NetworkProtectionUserDefaultsConstants.swift b/DuckDuckGo/NetworkProtection/AppAndExtensionAndAgentTargets/NetworkProtectionUserDefaultsConstants.swift deleted file mode 100644 index 165f2c37db..0000000000 --- a/DuckDuckGo/NetworkProtection/AppAndExtensionAndAgentTargets/NetworkProtectionUserDefaultsConstants.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// NetworkProtectionUserDefaultsConstants.swift -// -// Copyright © 2023 DuckDuckGo. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation - -/// Constants representing default values for NetP settings to be both accessible from Controller and Main Menu -enum NetworkProtectionUserDefaultsConstants { - - static let onDemandActivation = true - static let shouldConnectOnLogIn = false - static let shouldEnforceRoutes = false - static let shouldIncludeAllNetworks = false - static let shouldExcludeLocalNetworks = false - static let isConnectionTesterEnabled = true - -} From 74fd824b4acea713cbceb41e8c71d2b84f0642f2 Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Thu, 16 Nov 2023 19:30:21 +0100 Subject: [PATCH 16/40] Removes the show-vpn-settings feature flag --- DuckDuckGo.xcodeproj/project.pbxproj | 4 +- .../xcshareddata/swiftpm/Package.resolved | 8 ++++ .../NetworkProtectionDebugMenu.swift | 42 +++++++------------ ...etworkProtectionNavBarPopoverManager.swift | 15 +++---- .../NetworkProtectionTunnelController.swift | 37 ++++++++-------- .../Model/PreferencesSection.swift | 6 +-- .../Model/PreferencesSidebarModel.swift | 6 +-- .../View/PreferencesViewController.swift | 3 +- DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift | 27 ++++-------- DuckDuckGoVPN/UserText.swift | 1 - 10 files changed, 59 insertions(+), 90 deletions(-) diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 32ecf98e11..69c23ac221 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -4374,7 +4374,6 @@ 7BD1688D2AD4A4C400D24876 /* NetworkExtensionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkExtensionController.swift; sourceTree = ""; }; 7BD3AF5C2A8E7AF1006F9F56 /* KeychainType+ClientDefault.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "KeychainType+ClientDefault.swift"; sourceTree = ""; }; 7BD8679A2A9E9E000063B9F7 /* NetworkProtectionFeatureVisibility.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkProtectionFeatureVisibility.swift; sourceTree = ""; }; - 7BD952562B06236200BCCB7A /* BrowserServicesKit */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = BrowserServicesKit; path = ../../BrowserServicesKit; sourceTree = ""; }; 7BE146062A6A83C700C313B8 /* NetworkProtectionDebugMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionDebugMenu.swift; sourceTree = ""; }; 7BEC182D2AD5D89C00D30536 /* SystemExtensionManager */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = SystemExtensionManager; sourceTree = ""; }; 7BF1A9D72AE054D300FCA683 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -5584,7 +5583,6 @@ 378E279C2970217400FCADA2 /* LocalPackages */ = { isa = PBXGroup; children = ( - 7BD952562B06236200BCCB7A /* BrowserServicesKit */, 1E862A852A9FBD7000F84D4B /* Account */, 378E279D2970217400FCADA2 /* BuildToolPlugins */, 3192A2702A4C4E330084EA89 /* DataBrokerProtection */, @@ -14445,7 +14443,7 @@ repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit"; requirement = { kind = revision; - revision = 299e73ed6c9dc83f2b3935c4ba5d230cbb4e5489; + revision = 816e45fc079012039739d43906168f284d6326d3; }; }; AA06B6B52672AF8100F541C5 /* XCRemoteSwiftPackageReference "Sparkle" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 9e35eae6af..66e71ef658 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -9,6 +9,14 @@ "version" : "3.0.0" } }, + { + "identity" : "browserserviceskit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/duckduckgo/BrowserServicesKit", + "state" : { + "revision" : "816e45fc079012039739d43906168f284d6326d3" + } + }, { "identity" : "content-scope-scripts", "kind" : "remoteSourceControl", diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift index a62d6c6c46..1b2831a993 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift @@ -38,7 +38,6 @@ final class NetworkProtectionDebugMenu: NSMenu { private let registrationKeyValidityAutomaticItem = NSMenuItem(title: "Automatic", action: #selector(NetworkProtectionDebugMenu.setRegistrationKeyValidity)) private let resetToDefaults = NSMenuItem(title: "Reset Settings to defaults", action: #selector(NetworkProtectionDebugMenu.resetSettings)) - private let showVPNSettingsMenuItem = NSMenuItem(title: "Show in settings", action: #selector(NetworkProtectionDebugMenu.toggleShowVPNSettings)) private let exclusionsMenu = NSMenu() @@ -66,17 +65,22 @@ final class NetworkProtectionDebugMenu: NSMenu { super.init(title: "Network Protection") buildItems { - NSMenuItem(title: "Reset All State Keeping Invite", action: #selector(NetworkProtectionDebugMenu.resetAllKeepingInvite)) - .targetting(self) + NSMenuItem(title: "Reset") { + NSMenuItem(title: "Reset All State Keeping Invite", action: #selector(NetworkProtectionDebugMenu.resetAllKeepingInvite)) + .targetting(self) - NSMenuItem(title: "Reset All State", action: #selector(NetworkProtectionDebugMenu.resetAllState)) - .targetting(self) + NSMenuItem(title: "Reset All State", action: #selector(NetworkProtectionDebugMenu.resetAllState)) + .targetting(self) - NSMenuItem(title: "Remove System Extension and Login Items", action: #selector(NetworkProtectionDebugMenu.removeSystemExtensionAndAgents)) - .targetting(self) + resetToDefaults + .targetting(self) - NSMenuItem(title: "Reset Remote Messages", action: #selector(NetworkProtectionDebugMenu.resetNetworkProtectionRemoteMessages)) - .targetting(self) + NSMenuItem(title: "Remove System Extension and Login Items", action: #selector(NetworkProtectionDebugMenu.removeSystemExtensionAndAgents)) + .targetting(self) + + NSMenuItem(title: "Reset Remote Messages", action: #selector(NetworkProtectionDebugMenu.resetNetworkProtectionRemoteMessages)) + .targetting(self) + } NSMenuItem.separator() @@ -144,16 +148,6 @@ final class NetworkProtectionDebugMenu: NSMenu { NSMenuItem(title: "NetP Waitlist Feature Flag Overrides") .submenu(NetworkProtectionWaitlistFeatureFlagOverridesMenu()) - NSMenuItem(title: "VPN Settings") { - resetToDefaults - .targetting(self) - - NSMenuItem.separator() - - showVPNSettingsMenuItem - .targetting(self) - } - NSMenuItem.separator() NSMenuItem(title: "Kill Switch (alternative approach)") { @@ -311,10 +305,6 @@ final class NetworkProtectionDebugMenu: NSMenu { NetworkProtectionTunnelController().setExcludedRoute(addressRange, enabled: sender.state == .off)*/ } - @objc func toggleShowVPNSettings(_ sender: NSMenuItem) { - settings.showVPNSettings.toggle() - } - @objc func openAppContainerInFinder(_ sender: Any?) { let containerURL = URL.sandboxApplicationSupportURL NSWorkspace.shared.selectFile(nil, inFileViewerRootedAtPath: containerURL.path) @@ -392,14 +382,14 @@ final class NetworkProtectionDebugMenu: NSMenu { private func populateExclusionsMenuItems() { exclusionsMenu.removeAllItems() - for item in settings.exclusionList { + for item in settings.excludedRoutes { let menuItem: NSMenuItem switch item { case .section(let title): menuItem = NSMenuItem(title: title, action: nil, target: nil) menuItem.isEnabled = false - case .exclusion(range: let range, description: let description, default: _): + case .range(let range, let description): menuItem = NSMenuItem(title: "\(range)\(description != nil ? " (\(description!))" : "")", action: #selector(toggleExclusionAction), target: self, @@ -422,8 +412,6 @@ final class NetworkProtectionDebugMenu: NSMenu { updateRekeyValidityMenu() updateNetworkProtectionMenuItemsState() updateNetworkProtectionItems() - - showVPNSettingsMenuItem.state = settings.showVPNSettings ? .on : .off } private func updateEnvironmentMenu() { diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift index 2d0fb031c3..7d5b511b6a 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift @@ -64,6 +64,11 @@ final class NetworkProtectionNavBarPopoverManager { let popover = NetworkProtectionPopover(controller: controller, onboardingStatusPublisher: onboardingStatusPublisher, statusReporter: statusReporter) { var menuItems = [ + NetworkProtectionStatusView.Model.MenuItem( + name: UserText.networkProtectionNavBarStatusMenuVPNSettings, action: { + let appLauncher = AppLauncher(appBundleURL: Bundle.main.bundleURL) + await appLauncher.launchApp(withCommand: .showSettings) + }), NetworkProtectionStatusView.Model.MenuItem( name: UserText.networkProtectionNavBarStatusViewShareFeedback, action: { @@ -72,16 +77,6 @@ final class NetworkProtectionNavBarPopoverManager { }) ] - if settings.showVPNSettings { - menuItems.insert( - NetworkProtectionStatusView.Model.MenuItem( - name: UserText.networkProtectionNavBarStatusMenuVPNSettings, action: { - let appLauncher = AppLauncher(appBundleURL: Bundle.main.bundleURL) - await appLauncher.launchApp(withCommand: .showSettings) - }), - at: 0) - } - return menuItems } popover.delegate = delegate diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift index 5c98529bf5..2797e4f5d6 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift @@ -70,9 +70,11 @@ final class NetworkProtectionTunnelController: NetworkProtection.TunnelControlle // MARK: - User Defaults /// Test setting to exclude duckduckgo route from VPN + /* Temporarily disabled - https://app.asana.com/0/0/1205766100762904/f @MainActor @UserDefaultsWrapper(key: .networkProtectionExcludedRoutes, defaultValue: [:]) private(set) var excludedRoutesPreferences: [String: Bool] + */ @UserDefaultsWrapper(key: .networkProtectionOnboardingStatusRawValue, defaultValue: OnboardingStatus.default.rawValue, defaults: .shared) private(set) var onboardingStatusRawValue: OnboardingStatus.RawValue @@ -168,8 +170,7 @@ final class NetworkProtectionTunnelController: NetworkProtection.TunnelControlle .setSelectedServer, .setSelectedEnvironment, .setSelectedLocation, - .setShowInMenuBar, - .setShowVPNSettings: + .setShowInMenuBar: // Intentional no-op as this is handled by the extension or the agent's app delegate break } @@ -200,7 +201,6 @@ final class NetworkProtectionTunnelController: NetworkProtection.TunnelControlle } try await setupAndSave(tunnelManager) - updateRoutes() } private func relaySettingsChange(_ change: VPNSettings.Change) async throws { @@ -233,7 +233,6 @@ final class NetworkProtectionTunnelController: NetworkProtection.TunnelControlle protocolConfiguration.providerBundleIdentifier = NetworkProtectionBundle.extensionBundle().bundleIdentifier protocolConfiguration.providerConfiguration = [ NetworkProtectionOptionKey.defaultPixelHeaders: APIRequest.Headers().httpHeaders, - NetworkProtectionOptionKey.excludedRoutes: excludedRoutes().map(\.stringRepresentation) as NSArray, NetworkProtectionOptionKey.includedRoutes: includedRoutes().map(\.stringRepresentation) as NSArray ] @@ -241,10 +240,15 @@ final class NetworkProtectionTunnelController: NetworkProtection.TunnelControlle protocolConfiguration.disconnectOnSleep = false // kill switch - protocolConfiguration.enforceRoutes = settings.enforceRoutes + protocolConfiguration.enforceRoutes = true // settings.enforceRoutes // this setting breaks Connection Tester protocolConfiguration.includeAllNetworks = settings.includeAllNetworks - protocolConfiguration.excludeLocalNetworks = settings.excludeLocalNetworks + + // This is intentionally not used but left here for documentation purposes. + // The reason for this is that we want to have full control of the routes that + // are excluded, so instead of using this setting we're just configuring the + // excluded routes through our VPNSettings class, which our extension reads directly. + // protocolConfiguration.excludeLocalNetworks = settings.excludeLocalNetworks return protocolConfiguration }() @@ -391,7 +395,7 @@ final class NetworkProtectionTunnelController: NetworkProtection.TunnelControlle options[NetworkProtectionOptionKey.activationAttemptId] = UUID().uuidString as NSString options[NetworkProtectionOptionKey.authToken] = try tokenStore.fetchToken() as NSString? - options[NetworkProtectionOptionKey.selectedEnvironment] = settings.selectedEnvironment.rawValue as? NSString + options[NetworkProtectionOptionKey.selectedEnvironment] = settings.selectedEnvironment.rawValue as NSString options[NetworkProtectionOptionKey.selectedServer] = settings.selectedServer.stringValue as? NSString if case .custom(let keyValidity) = settings.registrationKeyValidity { @@ -465,9 +469,10 @@ final class NetworkProtectionTunnelController: NetworkProtection.TunnelControlle try await tunnelManager.saveToPreferences() } + /* Temporarily disabled until we fix this menu: https://app.asana.com/0/0/1205766100762904/f @MainActor private func excludedRoutes() -> [NetworkProtection.IPAddressRange] { - settings.exclusionList.compactMap { [excludedRoutesPreferences] item -> NetworkProtection.IPAddressRange? in + settings.excludedRoutes.compactMap { [excludedRoutesPreferences] item -> NetworkProtection.IPAddressRange? in guard case .exclusion(range: let range, description: _, default: let defaultValue) = item, excludedRoutesPreferences[range.stringRepresentation, default: defaultValue] == true else { return nil } @@ -480,7 +485,7 @@ final class NetworkProtectionTunnelController: NetworkProtection.TunnelControlle return range } - } + }*/ /// extra Included Routes appended to 0.0.0.0, ::/0 (peers) and interface.addresses @MainActor @@ -488,10 +493,11 @@ final class NetworkProtectionTunnelController: NetworkProtection.TunnelControlle [] } + + /* Temporarily disabled - https://app.asana.com/0/0/1205766100762904/f @MainActor func setExcludedRoute(_ route: String, enabled: Bool) { excludedRoutesPreferences[route] = enabled - updateRoutes() } @MainActor @@ -511,16 +517,7 @@ final class NetworkProtectionTunnelController: NetworkProtection.TunnelControlle return false } return excludedRoutesPreferences[route, default: defaultValue] - } - - func updateRoutes() { - Task { - guard let activeSession = try await ConnectionSessionUtilities.activeSession() else { return } - - try await activeSession.sendProviderMessage(.setIncludedRoutes(includedRoutes())) - try await activeSession.sendProviderMessage(.setExcludedRoutes(excludedRoutes())) - } - } + }*/ struct TunnelFailureError: LocalizedError { let errorDescription: String? diff --git a/DuckDuckGo/Preferences/Model/PreferencesSection.swift b/DuckDuckGo/Preferences/Model/PreferencesSection.swift index a87ef8f970..d63d17c327 100644 --- a/DuckDuckGo/Preferences/Model/PreferencesSection.swift +++ b/DuckDuckGo/Preferences/Model/PreferencesSection.swift @@ -24,7 +24,7 @@ struct PreferencesSection: Hashable, Identifiable { let panes: [PreferencePaneIdentifier] @MainActor - static func defaultSections(includingDuckPlayer: Bool, includingVPNSettings: Bool) -> [PreferencesSection] { + static func defaultSections(includingDuckPlayer: Bool) -> [PreferencesSection] { let regularPanes: [PreferencePaneIdentifier] = { #if SUBSCRIPTION var panes: [PreferencePaneIdentifier] = [.privacy, .subscription, .general, .appearance, .autofill, .downloads] @@ -45,9 +45,7 @@ struct PreferencesSection: Hashable, Identifiable { panes.append(.duckPlayer) } - if includingVPNSettings { - panes.append(.vpn) - } + panes.append(.vpn) return panes }() diff --git a/DuckDuckGo/Preferences/Model/PreferencesSidebarModel.swift b/DuckDuckGo/Preferences/Model/PreferencesSidebarModel.swift index d03b231c8f..f206797b00 100644 --- a/DuckDuckGo/Preferences/Model/PreferencesSidebarModel.swift +++ b/DuckDuckGo/Preferences/Model/PreferencesSidebarModel.swift @@ -19,7 +19,6 @@ import SwiftUI import BrowserServicesKit import Combine -import NetworkProtection final class PreferencesSidebarModel: ObservableObject { @@ -55,10 +54,9 @@ final class PreferencesSidebarModel: ObservableObject { convenience init( tabSwitcherTabs: [Tab.TabContent] = Tab.TabContent.displayableTabTypes, privacyConfigurationManager: PrivacyConfigurationManaging = ContentBlocking.shared.privacyConfigurationManager, - includeDuckPlayer: Bool, - settings: VPNSettings + includeDuckPlayer: Bool ) { - self.init(loadSections: { PreferencesSection.defaultSections(includingDuckPlayer: includeDuckPlayer, includingVPNSettings: settings.showVPNSettings) }, + self.init(loadSections: { PreferencesSection.defaultSections(includingDuckPlayer: includeDuckPlayer) }, tabSwitcherTabs: tabSwitcherTabs, privacyConfigurationManager: privacyConfigurationManager) } diff --git a/DuckDuckGo/Preferences/View/PreferencesViewController.swift b/DuckDuckGo/Preferences/View/PreferencesViewController.swift index c94166e6c9..6af604a501 100644 --- a/DuckDuckGo/Preferences/View/PreferencesViewController.swift +++ b/DuckDuckGo/Preferences/View/PreferencesViewController.swift @@ -25,8 +25,7 @@ final class PreferencesViewController: NSViewController { weak var delegate: BrowserTabSelectionDelegate? - let model = PreferencesSidebarModel(includeDuckPlayer: DuckPlayer.shared.isAvailable, - settings: .init(defaults: .shared)) + let model = PreferencesSidebarModel(includeDuckPlayer: DuckPlayer.shared.isAvailable) private var selectedTabIndexCancellable: AnyCancellable? private var selectedPreferencePaneCancellable: AnyCancellable? diff --git a/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift b/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift index 339d135c33..4c6b7c407a 100644 --- a/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift +++ b/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift @@ -140,25 +140,14 @@ final class DuckDuckGoVPNAppDelegate: NSObject, NSApplicationDelegate { statusReporter: statusReporter, controller: tunnelController, iconProvider: iconProvider) { - if tunnelSettings.showVPNSettings { - return [ - StatusBarMenu.MenuItem(name: UserText.networkProtectionStatusMenuVPNSettings, action: { [weak self] in - await self?.appLauncher.launchApp(withCommand: .showSettings) - }), - StatusBarMenu.MenuItem(name: UserText.networkProtectionStatusMenuShareFeedback, action: { [weak self] in - await self?.appLauncher.launchApp(withCommand: .shareFeedback) - }) - ] - } else { - return [ - StatusBarMenu.MenuItem(name: UserText.networkProtectionStatusMenuShareFeedback, action: { [weak self] in - await self?.appLauncher.launchApp(withCommand: .shareFeedback) - }), - StatusBarMenu.MenuItem(name: UserText.networkProtectionStatusMenuOpenDuckDuckGo, action: { [weak self] in - await self?.appLauncher.launchApp(withCommand: .justOpen) - }) - ] - } + [ + StatusBarMenu.MenuItem(name: UserText.networkProtectionStatusMenuVPNSettings, action: { [weak self] in + await self?.appLauncher.launchApp(withCommand: .showSettings) + }), + StatusBarMenu.MenuItem(name: UserText.networkProtectionStatusMenuShareFeedback, action: { [weak self] in + await self?.appLauncher.launchApp(withCommand: .shareFeedback) + }) + ] } } diff --git a/DuckDuckGoVPN/UserText.swift b/DuckDuckGoVPN/UserText.swift index 1ebb96993f..050d601727 100644 --- a/DuckDuckGoVPN/UserText.swift +++ b/DuckDuckGoVPN/UserText.swift @@ -22,6 +22,5 @@ final class UserText { // MARK: - Status Menu static let networkProtectionStatusMenuShareFeedback = NSLocalizedString("network.protection.status.menu.share.feedback", value: "Share Feedback...", comment: "The status menu 'Share Feedback' menu item") - static let networkProtectionStatusMenuOpenDuckDuckGo = NSLocalizedString("network.protection.status.menu.open.duckduckgo", value: "Open DuckDuckGo...", comment: "The status menu 'Open DuckDuckGo' menu item") static let networkProtectionStatusMenuVPNSettings = NSLocalizedString("network.protection.status.menu.vpn.settings", value: "VPN Settings...", comment: "The status menu 'VPN Settings' menu item") } From 5efc7b2efd86cf31815a256b223849a45228cdd5 Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Thu, 16 Nov 2023 20:00:52 +0100 Subject: [PATCH 17/40] Updates BSK --- DuckDuckGo.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 69c23ac221..e12c35b475 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -14443,7 +14443,7 @@ repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit"; requirement = { kind = revision; - revision = 816e45fc079012039739d43906168f284d6326d3; + revision = bcb6aa78bd7fd547ca0b6c0c133a99c7a14d4aad; }; }; AA06B6B52672AF8100F541C5 /* XCRemoteSwiftPackageReference "Sparkle" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 66e71ef658..f76855bd5f 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -14,7 +14,7 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/duckduckgo/BrowserServicesKit", "state" : { - "revision" : "816e45fc079012039739d43906168f284d6326d3" + "revision" : "bcb6aa78bd7fd547ca0b6c0c133a99c7a14d4aad" } }, { From 93d20f87d5979c29da9c14a42862131b05bdd64f Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Fri, 17 Nov 2023 00:49:08 +0100 Subject: [PATCH 18/40] Updates BSK --- DuckDuckGo.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index e12c35b475..cac82b0454 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -14443,7 +14443,7 @@ repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit"; requirement = { kind = revision; - revision = bcb6aa78bd7fd547ca0b6c0c133a99c7a14d4aad; + revision = 1552d499a22906f6426262a250a3778af42e5e67; }; }; AA06B6B52672AF8100F541C5 /* XCRemoteSwiftPackageReference "Sparkle" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index f76855bd5f..d6182d7b5a 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -14,7 +14,7 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/duckduckgo/BrowserServicesKit", "state" : { - "revision" : "bcb6aa78bd7fd547ca0b6c0c133a99c7a14d4aad" + "revision" : "1552d499a22906f6426262a250a3778af42e5e67" } }, { @@ -128,7 +128,7 @@ { "identity" : "trackerradarkit", "kind" : "remoteSourceControl", - "location" : "https://github.com/duckduckgo/TrackerRadarKit", + "location" : "https://github.com/duckduckgo/TrackerRadarKit.git", "state" : { "revision" : "4684440d03304e7638a2c8086895367e90987463", "version" : "1.2.1" From 4e3170d3d9ac2a7f5122ffe56f75158fb0c555be Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Fri, 17 Nov 2023 00:50:48 +0100 Subject: [PATCH 19/40] Fixes some swiftlint warnings --- .../BothAppTargets/NetworkProtectionTunnelController.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift index 2797e4f5d6..027afde75a 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift @@ -69,8 +69,8 @@ final class NetworkProtectionTunnelController: NetworkProtection.TunnelControlle // MARK: - User Defaults - /// Test setting to exclude duckduckgo route from VPN /* Temporarily disabled - https://app.asana.com/0/0/1205766100762904/f + /// Test setting to exclude duckduckgo route from VPN @MainActor @UserDefaultsWrapper(key: .networkProtectionExcludedRoutes, defaultValue: [:]) private(set) var excludedRoutesPreferences: [String: Bool] @@ -493,7 +493,6 @@ final class NetworkProtectionTunnelController: NetworkProtection.TunnelControlle [] } - /* Temporarily disabled - https://app.asana.com/0/0/1205766100762904/f @MainActor func setExcludedRoute(_ route: String, enabled: Bool) { From 0c9384d10a190e9e7ab8c6f49c32327571678b2b Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Fri, 17 Nov 2023 01:18:42 +0100 Subject: [PATCH 20/40] Updates BSK --- DuckDuckGo.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index cac82b0454..93a0e80532 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -14443,7 +14443,7 @@ repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit"; requirement = { kind = revision; - revision = 1552d499a22906f6426262a250a3778af42e5e67; + revision = 09c22b518388aed06f21609bcd6377f3b5b37310; }; }; AA06B6B52672AF8100F541C5 /* XCRemoteSwiftPackageReference "Sparkle" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index d6182d7b5a..d408bb641b 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -14,7 +14,7 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/duckduckgo/BrowserServicesKit", "state" : { - "revision" : "1552d499a22906f6426262a250a3778af42e5e67" + "revision" : "09c22b518388aed06f21609bcd6377f3b5b37310" } }, { From 4463e49ec6819c8e342eb063b8c8b5e43acddbce Mon Sep 17 00:00:00 2001 From: Sam Symons Date: Thu, 16 Nov 2023 16:32:58 -0800 Subject: [PATCH 21/40] Open a new window with a tab collection directly. --- DuckDuckGo/Windows/View/WindowControllersManager.swift | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/DuckDuckGo/Windows/View/WindowControllersManager.swift b/DuckDuckGo/Windows/View/WindowControllersManager.swift index 4d39a932be..ef5d3a04cc 100644 --- a/DuckDuckGo/Windows/View/WindowControllersManager.swift +++ b/DuckDuckGo/Windows/View/WindowControllersManager.swift @@ -188,11 +188,9 @@ extension WindowControllersManager { func showTab(with content: Tab.TabContent) { guard let windowController = self.mainWindowController else { Task { - WindowsManager.openNewWindow() - - // Not proud of this ugly hack... ideally openNewWindow() should let us know when the window is ready - try? await Task.sleep(interval: 0.5) - showTab(with: content) + let tabCollection = TabCollection(tabs: [Tab(content: content)]) + let tabCollectionViewModel = TabCollectionViewModel(tabCollection: tabCollection) + WindowsManager.openNewWindow(with: tabCollectionViewModel) } return From 55071ed73bd1506bf857ffbdae518cae3ccc56bd Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Fri, 17 Nov 2023 12:23:35 +0100 Subject: [PATCH 22/40] Corrects the copy for VPN settings --- DuckDuckGo/Common/Localizables/UserText.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/DuckDuckGo/Common/Localizables/UserText.swift b/DuckDuckGo/Common/Localizables/UserText.swift index b63b32db5e..6bc65fbf08 100644 --- a/DuckDuckGo/Common/Localizables/UserText.swift +++ b/DuckDuckGo/Common/Localizables/UserText.swift @@ -314,7 +314,7 @@ struct UserText { comment: "Connect on Login setting title") static let vpnConnectOnLoginSettingDescription = NSLocalizedString( "vpn.setting.description.connect.on.login", - value: "Automatically connect to the VPN service when you login", + value: "Automatically connect to the VPN service when you login.", comment: "Connect on Login setting description") static let vpnShowInMenuBarSettingTitle = NSLocalizedString( "vpn.setting.title.connect.on.login", @@ -322,15 +322,15 @@ struct UserText { comment: "Show VPN in menu bar setting title") static let vpnShowInMenuBarSettingDescription = NSLocalizedString( "vpn.setting.description.connect.on.login", - value: "Display VPN status in menu bar, next to the Wi-Fi and Battery", - comment: "Show VPN in menu bar setting description") + value: "Display VPN status in menu bar.", + comment: "Show VPN in menu bar setting description.") static let vpnAlwaysONSettingTitle = NSLocalizedString( "vpn.setting.title.always.on", value: "Always ON", comment: "Always ON setting title") static let vpnAlwaysOnSettingDescription = NSLocalizedString( "vpn.setting.description.always.on", - value: "Display VPN status in menu bar, next to the Wi-Fi and Battery", + value: "Automatically restores the VPN connection after interruption. For your security, this setting cannot be disabled.", comment: "Always ON setting description") static let vpnExcludeLocalNetworksSettingTitle = NSLocalizedString( "vpn.setting.title.exclude.local.networks", @@ -338,7 +338,7 @@ struct UserText { comment: "Exclude Local Networks setting title") static let vpnExcludeLocalNetworksSettingDescription = NSLocalizedString( "vpn.setting.description.exclude.local.networks", - value: "Let local traffic bypass the VPN and connect to devices on your local network, like a printer", + value: "Let local traffic bypass the VPN and connect to devices on your local network, like a printer.", comment: "Exclude Local Networks setting description") static let vpnSecureDNSSettingTitle = NSLocalizedString( "vpn.setting.title.secure.dns", @@ -350,7 +350,7 @@ struct UserText { comment: "Secure DNS setting description") static let vpnStatusChangeNotificationSettingTitle = NSLocalizedString( "vpn.setting.title.status.change.notification", - value: "Get notified if your connection drops or VPN status changes", + value: "Get notified if your connection drops or VPN status changes.", comment: "Status Change Notification setting title") static let uninstallVPNButtonTitle = NSLocalizedString( "vpn.button.title.uninstall.vpn", From 8c2c618ee1609573095cd42b3f51f291013a258a Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Fri, 17 Nov 2023 12:38:22 +0100 Subject: [PATCH 23/40] Adjusted several small mistakes in the copy --- DuckDuckGo/Common/Localizables/UserText.swift | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/DuckDuckGo/Common/Localizables/UserText.swift b/DuckDuckGo/Common/Localizables/UserText.swift index 6bc65fbf08..7b2cd7936f 100644 --- a/DuckDuckGo/Common/Localizables/UserText.swift +++ b/DuckDuckGo/Common/Localizables/UserText.swift @@ -310,23 +310,23 @@ struct UserText { static let vpnConnectOnLoginSettingTitle = NSLocalizedString( "vpn.setting.title.connect.on.login", - value: "Connect on Login", + value: "Connect on login", comment: "Connect on Login setting title") static let vpnConnectOnLoginSettingDescription = NSLocalizedString( "vpn.setting.description.connect.on.login", - value: "Automatically connect to the VPN service when you login.", + value: "Automatically turn on the DuckDuckGo VPN when you log in to your device.", comment: "Connect on Login setting description") static let vpnShowInMenuBarSettingTitle = NSLocalizedString( "vpn.setting.title.connect.on.login", value: "Show VPN in menu bar", - comment: "Show VPN in menu bar setting title") + comment: "Display VPN status in the menu bar.") static let vpnShowInMenuBarSettingDescription = NSLocalizedString( "vpn.setting.description.connect.on.login", value: "Display VPN status in menu bar.", comment: "Show VPN in menu bar setting description.") static let vpnAlwaysONSettingTitle = NSLocalizedString( "vpn.setting.title.always.on", - value: "Always ON", + value: "Always on", comment: "Always ON setting title") static let vpnAlwaysOnSettingDescription = NSLocalizedString( "vpn.setting.description.always.on", @@ -334,7 +334,7 @@ struct UserText { comment: "Always ON setting description") static let vpnExcludeLocalNetworksSettingTitle = NSLocalizedString( "vpn.setting.title.exclude.local.networks", - value: "Exclude Local Networks", + value: "Exclude local networks", comment: "Exclude Local Networks setting title") static let vpnExcludeLocalNetworksSettingDescription = NSLocalizedString( "vpn.setting.description.exclude.local.networks", @@ -346,11 +346,11 @@ struct UserText { comment: "Secure DNS setting title") static let vpnSecureDNSSettingDescription = NSLocalizedString( "vpn.setting.description.secure.dns", - value: "Prevents DNS leaks to your Internet service provider by routing DNS queries through the VPN tunnel to our own resolver. For your security, this feature cannot be disabled.", + value: "Prevents DNS leaks to your Internet service provider by routing DNS queries through the VPN tunnel to our own resolver. For your security, this setting cannot be disabled.", comment: "Secure DNS setting description") static let vpnStatusChangeNotificationSettingTitle = NSLocalizedString( "vpn.setting.title.status.change.notification", - value: "Get notified if your connection drops or VPN status changes.", + value: "Get notified if your connection drops or VPN status changes", comment: "Status Change Notification setting title") static let uninstallVPNButtonTitle = NSLocalizedString( "vpn.button.title.uninstall.vpn", From 26ca9433b8d8e6ac9ca8c3bcd9bb62fd3ab66790 Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Fri, 17 Nov 2023 12:45:24 +0100 Subject: [PATCH 24/40] Fixes copy errors --- DuckDuckGo/Common/Localizables/UserText.swift | 4 ++-- DuckDuckGo/Preferences/View/PreferencesVPNView.swift | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/DuckDuckGo/Common/Localizables/UserText.swift b/DuckDuckGo/Common/Localizables/UserText.swift index 7b2cd7936f..e1980dd153 100644 --- a/DuckDuckGo/Common/Localizables/UserText.swift +++ b/DuckDuckGo/Common/Localizables/UserText.swift @@ -302,7 +302,7 @@ struct UserText { // VPN Setting Titles - static let manageVPNSettingsTitle = NSLocalizedString("manage.vpn.settings.title", value: "Manage VPN", comment: "Manage VPN section title in VPN settings") + static let vpnSettingsTitle = NSLocalizedString("vpn.settings.title", value: "VPN Settings", comment: "VPN Settings section title in VPN settings") static let vpnNotificationsSettingsTitle = NSLocalizedString("vpn.notifications.settings.title", value: "VPN Notifications", comment: "VPN Notifications section title in VPN settings") static let vpnAdvancedSettingsTitle = NSLocalizedString("vpn.advanced.settings.title", value: "Advanced", comment: "VPN Advanced section title in VPN settings") @@ -362,7 +362,7 @@ struct UserText { static let uninstallVPNAlertTitle = NSLocalizedString("vpn.uninstall.alert.title", value: "Are you sure you want to uninstall the VPN?", comment: "Alert title when the user selects to uninstall our VPN") static let uninstallVPNInformativeText = NSLocalizedString( "vpn.uninstall.alert.informative.text", - value: "Uninstalling the DuckDuckGo VPN will disconnect any active VPN connections and remove it from your device.", + value: "Uninstalling the DuckDuckGo VPN will disconnect the VPN and remove it from your device.", comment: "Informative text for the alert that comes up when the user decides to uninstall our VPN") // Misc diff --git a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift index 7a15df0884..b072b5180b 100644 --- a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift +++ b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift @@ -34,7 +34,7 @@ extension Preferences { // SECTION: Manage VPN PreferencePaneSection { - TextMenuItemHeader(text: UserText.manageVPNSettingsTitle) + TextMenuItemHeader(text: UserText.vpnSettingsTitle) ToggleMenuItem(title: UserText.vpnConnectOnLoginSettingTitle, isOn: $model.connectOnLogin) TextMenuItemCaption(text: UserText.vpnConnectOnLoginSettingDescription) From 038208f03aa3ec7b948e9d50f1dc24f91804f0dc Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Mon, 20 Nov 2023 11:12:01 +0100 Subject: [PATCH 25/40] Fixes the VPN settings so that they're only visible if NetP has been enabled --- .../Preferences/Model/PreferencesSection.swift | 6 ++++-- .../Preferences/Model/PreferencesSidebarModel.swift | 8 +++++++- .../NetworkProtectionFeatureVisibility.swift | 13 ++++++++++++- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/DuckDuckGo/Preferences/Model/PreferencesSection.swift b/DuckDuckGo/Preferences/Model/PreferencesSection.swift index d63d17c327..e5ac478c96 100644 --- a/DuckDuckGo/Preferences/Model/PreferencesSection.swift +++ b/DuckDuckGo/Preferences/Model/PreferencesSection.swift @@ -24,7 +24,7 @@ struct PreferencesSection: Hashable, Identifiable { let panes: [PreferencePaneIdentifier] @MainActor - static func defaultSections(includingDuckPlayer: Bool) -> [PreferencesSection] { + static func defaultSections(includingDuckPlayer: Bool, includingVPN: Bool) -> [PreferencesSection] { let regularPanes: [PreferencePaneIdentifier] = { #if SUBSCRIPTION var panes: [PreferencePaneIdentifier] = [.privacy, .subscription, .general, .appearance, .autofill, .downloads] @@ -45,7 +45,9 @@ struct PreferencesSection: Hashable, Identifiable { panes.append(.duckPlayer) } - panes.append(.vpn) + if includingVPN { + panes.append(.vpn) + } return panes }() diff --git a/DuckDuckGo/Preferences/Model/PreferencesSidebarModel.swift b/DuckDuckGo/Preferences/Model/PreferencesSidebarModel.swift index f206797b00..97ce9fc602 100644 --- a/DuckDuckGo/Preferences/Model/PreferencesSidebarModel.swift +++ b/DuckDuckGo/Preferences/Model/PreferencesSidebarModel.swift @@ -56,7 +56,13 @@ final class PreferencesSidebarModel: ObservableObject { privacyConfigurationManager: PrivacyConfigurationManaging = ContentBlocking.shared.privacyConfigurationManager, includeDuckPlayer: Bool ) { - self.init(loadSections: { PreferencesSection.defaultSections(includingDuckPlayer: includeDuckPlayer) }, + let loadSections = { + let includingVPN = DefaultNetworkProtectionVisibility().isEnabled + + return PreferencesSection.defaultSections(includingDuckPlayer: includeDuckPlayer, includingVPN: includingVPN) + } + + self.init(loadSections: loadSections, tabSwitcherTabs: tabSwitcherTabs, privacyConfigurationManager: privacyConfigurationManager) } diff --git a/DuckDuckGo/Waitlist/NetworkProtectionFeatureVisibility.swift b/DuckDuckGo/Waitlist/NetworkProtectionFeatureVisibility.swift index e4eb4daebb..f2c613d7a5 100644 --- a/DuckDuckGo/Waitlist/NetworkProtectionFeatureVisibility.swift +++ b/DuckDuckGo/Waitlist/NetworkProtectionFeatureVisibility.swift @@ -34,6 +34,7 @@ struct DefaultNetworkProtectionVisibility: NetworkProtectionFeatureVisibility { private let featureDisabler: NetworkProtectionFeatureDisabling private let featureOverrides: WaitlistBetaOverriding private let networkProtectionFeatureActivation: NetworkProtectionFeatureActivation + private let networkProtectionWaitlist = NetworkProtectionWaitlist() private let privacyConfigurationManager: PrivacyConfigurationManaging var waitlistIsOngoing: Bool { @@ -63,6 +64,10 @@ struct DefaultNetworkProtectionVisibility: NetworkProtectionFeatureVisibility { isEasterEggUser || waitlistIsOngoing } + var isEnabled: Bool { + isEasterEggUser || (waitlistIsOngoing && isInvitedWaitlistUser) + } + /// Easter egg users can be identified by them being internal users and having an auth token (NetP being activated). /// private var isEasterEggUser: Bool { @@ -77,7 +82,13 @@ struct DefaultNetworkProtectionVisibility: NetworkProtectionFeatureVisibility { /// Waitlist users are users that have the waitlist enabled and active /// private var isWaitlistUser: Bool { - NetworkProtectionWaitlist().waitlistStorage.isWaitlistUser + networkProtectionWaitlist.waitlistStorage.isWaitlistUser + } + + /// Waitlist users are users that have the waitlist enabled and active and are invited + /// + private var isInvitedWaitlistUser: Bool { + networkProtectionWaitlist.waitlistStorage.isWaitlistUser && networkProtectionWaitlist.waitlistStorage.isInvited } private var isWaitlistBetaActive: Bool { From 0ab83fe47a471f4b89a2ea022bdbc5491910de6f Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Mon, 20 Nov 2023 12:04:18 +0100 Subject: [PATCH 26/40] Hides the 'Uninstall...' button when the VPN is not installed --- ...UserDefaults+NetworkProtectionShared.swift | 12 +++++++++ .../Model/VPNPreferencesModel.swift | 26 +++++++++++++++++-- .../Preferences/View/PreferencesVPNView.swift | 10 +++---- .../NetworkProtectionFeatureDisabler.swift | 7 +---- .../TunnelControllerIPCService.swift | 17 ++++++++++-- 5 files changed, 57 insertions(+), 15 deletions(-) diff --git a/DuckDuckGo/NetworkProtection/AppAndExtensionAndAgentTargets/UserDefaults+NetworkProtectionShared.swift b/DuckDuckGo/NetworkProtection/AppAndExtensionAndAgentTargets/UserDefaults+NetworkProtectionShared.swift index 97925a857f..fc0fc453f2 100644 --- a/DuckDuckGo/NetworkProtection/AppAndExtensionAndAgentTargets/UserDefaults+NetworkProtectionShared.swift +++ b/DuckDuckGo/NetworkProtection/AppAndExtensionAndAgentTargets/UserDefaults+NetworkProtectionShared.swift @@ -42,7 +42,19 @@ extension UserDefaults { } } + var networkProtectionOnboardingStatus: OnboardingStatus { + get { + OnboardingStatus(rawValue: networkProtectionOnboardingStatusRawValue) ?? .default + } + + set { + networkProtectionOnboardingStatusRawValue = newValue.rawValue + } + } + var networkProtectionOnboardingStatusPublisher: AnyPublisher { + // It's important to subscribe to the publisher for the raw value, since this + // is the way to get KVO when the UserDefaults are modified by another process. publisher(for: \.networkProtectionOnboardingStatusRawValue).map { value in OnboardingStatus(rawValue: value) ?? .default }.eraseToAnyPublisher() diff --git a/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift b/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift index b12a211e24..0929589430 100644 --- a/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift +++ b/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift @@ -16,9 +16,11 @@ // limitations under the License. // +import AppKit +import Combine import Foundation import NetworkProtection -import AppKit +import NetworkProtectionUI final class VPNPreferencesModel: ObservableObject { @@ -50,15 +52,35 @@ final class VPNPreferencesModel: ObservableObject { } } + @Published var showUninstallVPN: Bool + + private var onboardingStatus: OnboardingStatus { + didSet { + showUninstallVPN = onboardingStatus != .default + } + } + private let settings: VPNSettings + private var cancellables = Set() - init(settings: VPNSettings = .init(defaults: .shared)) { + init(settings: VPNSettings = .init(defaults: .shared), + defaults: UserDefaults = .shared) { self.settings = settings connectOnLogin = settings.connectOnLogin excludeLocalNetworks = settings.excludeLocalNetworks notifyStatusChanges = settings.notifyStatusChanges showInMenuBar = settings.showInMenuBar + showUninstallVPN = defaults.networkProtectionOnboardingStatus != .default + onboardingStatus = defaults.networkProtectionOnboardingStatus + + subscribeToOnboardingStatusChanges(defaults: defaults) + } + + func subscribeToOnboardingStatusChanges(defaults: UserDefaults) { + defaults.networkProtectionOnboardingStatusPublisher + .assign(to: \.onboardingStatus, onWeaklyHeld: self) + .store(in: &cancellables) } func uninstallVPN() { diff --git a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift index b072b5180b..e09fe649da 100644 --- a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift +++ b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift @@ -64,11 +64,11 @@ extension Preferences { // SECTION: Uninstall - PreferencePaneSection { - TextMenuItemHeader(text: UserText.vpnAdvancedSettingsTitle) - - Button(UserText.uninstallVPNButtonTitle) { - model.uninstallVPN() + if model.showUninstallVPN { + PreferencePaneSection { + Button(UserText.uninstallVPNButtonTitle) { + model.uninstallVPN() + } } } } diff --git a/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift b/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift index 47dfa668e8..27688dbf77 100644 --- a/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift +++ b/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift @@ -99,10 +99,6 @@ final class NetworkProtectionFeatureDisabler: NetworkProtectionFeatureDisabling func removeSystemExtension() async { await ipcClient.debugCommand(.removeSystemExtension) - -#if NETP_SYSTEM_EXTENSION - userDefaults.networkProtectionOnboardingStatusRawValue = OnboardingStatus.default.rawValue -#endif } private func unpinNetworkProtection() { @@ -127,10 +123,9 @@ final class NetworkProtectionFeatureDisabler: NetworkProtectionFeatureDisabling } } } - + private func resetUserDefaults() { settings.resetToDefaults() - userDefaults.networkProtectionOnboardingStatusRawValue = OnboardingStatus.default.rawValue } } diff --git a/DuckDuckGoVPN/TunnelControllerIPCService.swift b/DuckDuckGoVPN/TunnelControllerIPCService.swift index 3210cf2be2..3a2e8ee658 100644 --- a/DuckDuckGoVPN/TunnelControllerIPCService.swift +++ b/DuckDuckGoVPN/TunnelControllerIPCService.swift @@ -20,6 +20,7 @@ import Combine import Foundation import NetworkProtection import NetworkProtectionIPC +import NetworkProtectionUI /// Takes care of handling incoming IPC requests from clients that need to be relayed to the tunnel, and handling state /// changes that need to be relayed back to IPC clients. @@ -33,15 +34,18 @@ final class TunnelControllerIPCService { private let server: NetworkProtectionIPC.TunnelControllerIPCServer private let statusReporter: NetworkProtectionStatusReporter private var cancellables = Set() + private let defaults: UserDefaults init(tunnelController: TunnelController, networkExtensionController: NetworkExtensionController, - statusReporter: NetworkProtectionStatusReporter) { + statusReporter: NetworkProtectionStatusReporter, + defaults: UserDefaults = .shared) { self.tunnelController = tunnelController self.networkExtensionController = networkExtensionController server = .init(machServiceName: Bundle.main.bundleIdentifier!) self.statusReporter = statusReporter + self.defaults = defaults subscribeToErrorChanges() subscribeToStatusUpdates() @@ -118,7 +122,16 @@ extension TunnelControllerIPCService: IPCServerInterface { switch command { case .removeSystemExtension: await VPNConfigurationManager().removeVPNConfiguration() - try? await networkExtensionController.deactivateSystemExtension() + defaults.networkProtectionOnboardingStatus = .isOnboarding(step: .userNeedsToAllowVPNConfiguration) + +#if NETP_SYSTEM_EXTENSION + do { + try await networkExtensionController.deactivateSystemExtension() + defaults.networkProtectionOnboardingStatus = .default + } catch { + // No-op: for now we're not handling this type of error. + } +#endif case .expireRegistrationKey: // Intentional no-op: handled by the extension break From dec1643c5ba0dd93c4db7a99bf911e7b024b28fb Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Mon, 20 Nov 2023 12:19:43 +0100 Subject: [PATCH 27/40] Makes several UI adjustments --- DuckDuckGo/Common/Localizables/UserText.swift | 4 ++-- DuckDuckGo/Preferences/View/PreferencesVPNView.swift | 8 ++++---- .../Waitlist/NetworkProtectionFeatureDisabler.swift | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/DuckDuckGo/Common/Localizables/UserText.swift b/DuckDuckGo/Common/Localizables/UserText.swift index e1980dd153..478cbce8a9 100644 --- a/DuckDuckGo/Common/Localizables/UserText.swift +++ b/DuckDuckGo/Common/Localizables/UserText.swift @@ -302,8 +302,8 @@ struct UserText { // VPN Setting Titles - static let vpnSettingsTitle = NSLocalizedString("vpn.settings.title", value: "VPN Settings", comment: "VPN Settings section title in VPN settings") - static let vpnNotificationsSettingsTitle = NSLocalizedString("vpn.notifications.settings.title", value: "VPN Notifications", comment: "VPN Notifications section title in VPN settings") + static let vpnGeneralTitle = NSLocalizedString("vpn.general.title", value: "General", comment: "General section title in VPN settings") + static let vpnNotificationsSettingsTitle = NSLocalizedString("vpn.notifications.settings.title", value: "Notifications", comment: "Notifications section title in VPN settings") static let vpnAdvancedSettingsTitle = NSLocalizedString("vpn.advanced.settings.title", value: "Advanced", comment: "VPN Advanced section title in VPN settings") // VPN Settings diff --git a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift index e09fe649da..0ac9d080aa 100644 --- a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift +++ b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift @@ -34,7 +34,7 @@ extension Preferences { // SECTION: Manage VPN PreferencePaneSection { - TextMenuItemHeader(text: UserText.vpnSettingsTitle) + TextMenuItemHeader(text: UserText.vpnGeneralTitle) ToggleMenuItem(title: UserText.vpnConnectOnLoginSettingTitle, isOn: $model.connectOnLogin) TextMenuItemCaption(text: UserText.vpnConnectOnLoginSettingDescription) @@ -42,13 +42,13 @@ extension Preferences { ToggleMenuItem(title: UserText.vpnShowInMenuBarSettingTitle, isOn: $model.showInMenuBar) TextMenuItemCaption(text: UserText.vpnShowInMenuBarSettingDescription) + ToggleMenuItem(title: UserText.vpnExcludeLocalNetworksSettingTitle, isOn: $model.excludeLocalNetworks) + TextMenuItemCaption(text: UserText.vpnExcludeLocalNetworksSettingDescription) + ToggleMenuItem(title: UserText.vpnAlwaysONSettingTitle, isOn: $model.alwaysON) .disabled(true) TextMenuItemCaption(text: UserText.vpnAlwaysOnSettingDescription) - ToggleMenuItem(title: UserText.vpnExcludeLocalNetworksSettingTitle, isOn: $model.excludeLocalNetworks) - TextMenuItemCaption(text: UserText.vpnExcludeLocalNetworksSettingDescription) - ToggleMenuItem(title: UserText.vpnSecureDNSSettingTitle, isOn: $model.secureDNS) .disabled(true) TextMenuItemCaption(text: UserText.vpnSecureDNSSettingDescription) diff --git a/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift b/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift index 27688dbf77..0e7b2782db 100644 --- a/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift +++ b/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift @@ -123,7 +123,7 @@ final class NetworkProtectionFeatureDisabler: NetworkProtectionFeatureDisabling } } } - + private func resetUserDefaults() { settings.resetToDefaults() } From c2655e88bc65c20a97caffdfe39a56e5381d08e2 Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Mon, 20 Nov 2023 12:25:03 +0100 Subject: [PATCH 28/40] Removes some unnecessary code --- DuckDuckGo/Windows/View/WindowControllersManager.swift | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/DuckDuckGo/Windows/View/WindowControllersManager.swift b/DuckDuckGo/Windows/View/WindowControllersManager.swift index ef5d3a04cc..5a2beeadfe 100644 --- a/DuckDuckGo/Windows/View/WindowControllersManager.swift +++ b/DuckDuckGo/Windows/View/WindowControllersManager.swift @@ -187,12 +187,9 @@ extension WindowControllersManager { func showTab(with content: Tab.TabContent) { guard let windowController = self.mainWindowController else { - Task { - let tabCollection = TabCollection(tabs: [Tab(content: content)]) - let tabCollectionViewModel = TabCollectionViewModel(tabCollection: tabCollection) - WindowsManager.openNewWindow(with: tabCollectionViewModel) - } - + let tabCollection = TabCollection(tabs: [Tab(content: content)]) + let tabCollectionViewModel = TabCollectionViewModel(tabCollection: tabCollection) + WindowsManager.openNewWindow(with: tabCollectionViewModel) return } From 21d86396015a909c0e83347d0b92c3fa70916561 Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Wed, 22 Nov 2023 17:52:38 +0100 Subject: [PATCH 29/40] Code cleanup, and ship review changes --- .../xcshareddata/swiftpm/Package.resolved | 12 +--- .../InfoSubtle-16.imageset/Contents.json | 12 ++++ .../InfoSubtle-16.imageset/Info-Subtle-16.pdf | Bin 0 -> 1661 bytes DuckDuckGo/Common/Localizables/UserText.swift | 24 +------- .../NetworkProtectionOnboardingMenu.swift | 2 +- DuckDuckGo/Preferences/View/Preferences.swift | 34 +++++++++++- .../Preferences/View/PreferencesVPNView.swift | 52 +++++++++++++----- .../UserText+NetworkProtectionUI.swift | 2 +- .../OnboardingStepViewModel.swift | 2 +- 9 files changed, 88 insertions(+), 52 deletions(-) create mode 100644 DuckDuckGo/Assets.xcassets/Images/InfoSubtle-16.imageset/Contents.json create mode 100644 DuckDuckGo/Assets.xcassets/Images/InfoSubtle-16.imageset/Info-Subtle-16.pdf diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index d408bb641b..8edafb9d05 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -9,14 +9,6 @@ "version" : "3.0.0" } }, - { - "identity" : "browserserviceskit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/duckduckgo/BrowserServicesKit", - "state" : { - "revision" : "09c22b518388aed06f21609bcd6377f3b5b37310" - } - }, { "identity" : "content-scope-scripts", "kind" : "remoteSourceControl", @@ -31,8 +23,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/duckduckgo/duckduckgo-autofill.git", "state" : { - "revision" : "c8e895c8fd50dc76e8d8dc827a636ad77b7f46ff", - "version" : "9.0.0" + "revision" : "93677cc02cfe650ce7f417246afd0e8e972cd83e", + "version" : "10.0.0" } }, { diff --git a/DuckDuckGo/Assets.xcassets/Images/InfoSubtle-16.imageset/Contents.json b/DuckDuckGo/Assets.xcassets/Images/InfoSubtle-16.imageset/Contents.json new file mode 100644 index 0000000000..d006c9eda6 --- /dev/null +++ b/DuckDuckGo/Assets.xcassets/Images/InfoSubtle-16.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Info-Subtle-16.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/DuckDuckGo/Assets.xcassets/Images/InfoSubtle-16.imageset/Info-Subtle-16.pdf b/DuckDuckGo/Assets.xcassets/Images/InfoSubtle-16.imageset/Info-Subtle-16.pdf new file mode 100644 index 0000000000000000000000000000000000000000..734d44d694451bf1a9128fd32c64b193df639c69 GIT binary patch literal 1661 zcmZvdTW=FF5QX3UEBsQaMZ%f!-BMMFwiF>il$5uMhp^eULCr2?Q&jl%9B=m41V2RH z&*Sl&|2HWp%%OkOpv`qnhoeT&%_H zvi!X&%K5uL;&<+2Pu-RICLlAIQaso%@rfs02He+96|~c|Czf zxyV6l$y!;CI^;ZUB|L5zNFj#!fep3nFVUEwK$V@o@th%^eZM%AIHE#~J4QOHnyelw zEyRO}%0|QR2a(3v6iKc{P{Aa}W&(rKG1%ZGyJLP`#NS(gNHXr$`l|LRmBC`tV8Ixd0)%pM!H{%{S!;G6#^|U` zuAB^BoOYjuc-%h3Cu^Yw-tRejNV4;HuS6xjh}wP!8NRSS)4Xizr%h2dGB>q( zm+qpjwq=DAb4Tmp^-(2mpEu>5AQ{B2!Q@}*oik1XcLOhQJCoIb4C>5dK%8ImePnP=FQW{; zynTe0(xdHWv3e{wBH!NoOW1MT)a&v@9 + let spacing: CGFloat + + var body: some View { + Toggle(isOn: isOn) { + VStack(alignment: .leading, spacing: 4) { + Text(title) + .fixMultilineScrollableText() + + TextMenuItemCaption(text: description) + } + }.toggleStyle(.checkbox) + } + } + + struct SpacedCheckbox: View where Content: View { + @ViewBuilder let content: () -> Content + + var body: some View { + VStack(alignment: .leading) { + content() + }.padding(.bottom, Const.Spacing.groupedCheckboxesSeparation) + } + } } diff --git a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift index 0ac9d080aa..735115de73 100644 --- a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift +++ b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift @@ -36,22 +36,46 @@ extension Preferences { PreferencePaneSection { TextMenuItemHeader(text: UserText.vpnGeneralTitle) - ToggleMenuItem(title: UserText.vpnConnectOnLoginSettingTitle, isOn: $model.connectOnLogin) - TextMenuItemCaption(text: UserText.vpnConnectOnLoginSettingDescription) - - ToggleMenuItem(title: UserText.vpnShowInMenuBarSettingTitle, isOn: $model.showInMenuBar) - TextMenuItemCaption(text: UserText.vpnShowInMenuBarSettingDescription) + SpacedCheckbox { + ToggleMenuItem(title: UserText.vpnConnectOnLoginSettingTitle, isOn: $model.connectOnLogin) + } - ToggleMenuItem(title: UserText.vpnExcludeLocalNetworksSettingTitle, isOn: $model.excludeLocalNetworks) - TextMenuItemCaption(text: UserText.vpnExcludeLocalNetworksSettingDescription) + SpacedCheckbox { + ToggleMenuItem(title: UserText.vpnShowInMenuBarSettingTitle, isOn: $model.showInMenuBar) + } - ToggleMenuItem(title: UserText.vpnAlwaysONSettingTitle, isOn: $model.alwaysON) - .disabled(true) - TextMenuItemCaption(text: UserText.vpnAlwaysOnSettingDescription) + SpacedCheckbox { + ToggleMenuItemWithDescription(title: UserText.vpnExcludeLocalNetworksSettingTitle, + description: UserText.vpnExcludeLocalNetworksSettingDescription, + isOn: $model.excludeLocalNetworks, + spacing: 12) + } - ToggleMenuItem(title: UserText.vpnSecureDNSSettingTitle, isOn: $model.secureDNS) - .disabled(true) - TextMenuItemCaption(text: UserText.vpnSecureDNSSettingDescription) + VStack(alignment: .leading) { + HStack(spacing: 10) { + Image("InfoSubtle-16") + + VStack { + HStack { + Text(UserText.vpnSecureDNSSettingDescription) + .padding(0) + .font(.system(size: 11)) + .foregroundColor(Color("BlackWhite60")) + .multilineTextAlignment(.leading) + .fixMultilineScrollableText() + + Spacer() + } + } + .frame(idealWidth: .infinity, maxWidth: .infinity) + + Spacer() + } + }.frame(alignment: .topLeading) + .frame(idealWidth: .infinity, maxWidth: .infinity) + .padding(10) + .background(Color("BlackWhite10")) + .roundedBorder() } // SECTION: VPN Notifications @@ -59,7 +83,7 @@ extension Preferences { PreferencePaneSection { TextMenuItemHeader(text: UserText.vpnNotificationsSettingsTitle) - ToggleMenuItem(title: UserText.vpnStatusChangeNotificationSettingTitle, isOn: $model.notifyStatusChanges) + ToggleMenuItem(title: "VPN connection drops or status changes", isOn: $model.notifyStatusChanges) } // SECTION: Uninstall diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Extensions/UserText+NetworkProtectionUI.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Extensions/UserText+NetworkProtectionUI.swift index 5a35ae2b4d..a73363a9c8 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Extensions/UserText+NetworkProtectionUI.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Extensions/UserText+NetworkProtectionUI.swift @@ -30,7 +30,7 @@ final class UserText { // MARK: - Onboarding - static let networkProtectionOnboardingAllowExtensionTitle = NSLocalizedString("network.protection.onboarding.allow.extension.title", value: "Allow System Extension", comment: "Title for the onboarding allow-extension step") + static let networkProtectionOnboardingInstallExtensionTitle = NSLocalizedString("network.protection.onboarding.install.extension.title", value: "Install VPN System Extension", comment: "Title for the onboarding install-vpn-extension step") static let networkProtectionOnboardingAllowExtensionDescPrefix = NSLocalizedString("network.protection.onboarding.allow.extension.desc.prefix", value: "Open System Settings to Privacy & Security. Scroll and select ", comment: "Non-bold prefix for the onboarding allow-extension description") static let networkProtectionOnboardingAllowExtensionDescAllow = NSLocalizedString("network.protection.onboarding.allow.extension.desc.allow", value: "Allow", comment: "'Allow' word between the prefix and suffix for the onboarding allow-extension description") static let networkProtectionOnboardingAllowExtensionDescSuffix = NSLocalizedString("network.protection.onboarding.allow.extension.desc.suffix", value: " for DuckDuckGo software.", comment: "Non-bold suffix for the onboarding allow-extension description") diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/OnboardingStepView/OnboardingStepViewModel.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/OnboardingStepView/OnboardingStepViewModel.swift index de6d796351..72871f1140 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/OnboardingStepView/OnboardingStepViewModel.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/OnboardingStepView/OnboardingStepViewModel.swift @@ -54,7 +54,7 @@ extension OnboardingStepView { var title: String { switch step { case .userNeedsToAllowExtension: - return UserText.networkProtectionOnboardingAllowExtensionTitle + return UserText.networkProtectionOnboardingInstallExtensionTitle case .userNeedsToAllowVPNConfiguration: return UserText.networkProtectionOnboardingAllowVPNTitle } From 94a95f65532549a31a5197dc21fe7bcb2583301b Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Wed, 22 Nov 2023 17:53:15 +0100 Subject: [PATCH 30/40] Updates BSK --- .../xcshareddata/swiftpm/Package.resolved | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 8edafb9d05..d408bb641b 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -9,6 +9,14 @@ "version" : "3.0.0" } }, + { + "identity" : "browserserviceskit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/duckduckgo/BrowserServicesKit", + "state" : { + "revision" : "09c22b518388aed06f21609bcd6377f3b5b37310" + } + }, { "identity" : "content-scope-scripts", "kind" : "remoteSourceControl", @@ -23,8 +31,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/duckduckgo/duckduckgo-autofill.git", "state" : { - "revision" : "93677cc02cfe650ce7f417246afd0e8e972cd83e", - "version" : "10.0.0" + "revision" : "c8e895c8fd50dc76e8d8dc827a636ad77b7f46ff", + "version" : "9.0.0" } }, { From e61f3934ad149d204b90da222af73b24b76e644a Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Thu, 23 Nov 2023 13:12:13 +0100 Subject: [PATCH 31/40] Remove the VPN settings pane when the VPN is uninstalled --- .../NetworkProtectionNavBarButtonModel.swift | 1 - .../Model/PreferencesSidebarModel.swift | 31 +++++++++++++++++-- .../NetworkProtectionFeatureDisabler.swift | 4 +-- .../NetworkProtectionFeatureVisibility.swift | 16 ++++++++-- 4 files changed, 44 insertions(+), 8 deletions(-) diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarButtonModel.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarButtonModel.swift index a24bc8ee15..d9473f1efe 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarButtonModel.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarButtonModel.swift @@ -78,7 +78,6 @@ final class NetworkProtectionNavBarButtonModel: NSObject, ObservableObject { statusReporter: NetworkProtectionStatusReporter? = nil, iconProvider: IconProvider = NavigationBarIconProvider()) { - let vpnBundleID = Bundle.main.vpnMenuAgentBundleId self.popoverManager = popoverManager let ipcClient = popoverManager.ipcClient diff --git a/DuckDuckGo/Preferences/Model/PreferencesSidebarModel.swift b/DuckDuckGo/Preferences/Model/PreferencesSidebarModel.swift index 97ce9fc602..c20f61e4bd 100644 --- a/DuckDuckGo/Preferences/Model/PreferencesSidebarModel.swift +++ b/DuckDuckGo/Preferences/Model/PreferencesSidebarModel.swift @@ -28,6 +28,8 @@ final class PreferencesSidebarModel: ObservableObject { @Published var selectedTabIndex: Int = 0 @Published private(set) var selectedPane: PreferencePaneIdentifier = .general + // MARK: - Initializers + init( loadSections: @escaping () -> [PreferencesSection], tabSwitcherTabs: [Tab.TabContent], @@ -35,10 +37,11 @@ final class PreferencesSidebarModel: ObservableObject { ) { self.loadSections = loadSections self.tabSwitcherTabs = tabSwitcherTabs + resetTabSelectionIfNeeded() refreshSections() - privacyConfigCancellable = privacyConfigurationManager.updatesPublisher + privacyConfigurationManager.updatesPublisher .map { [weak privacyConfigurationManager] in privacyConfigurationManager?.privacyConfig.isEnabled(featureKey: .duckPlayer) == true } @@ -48,6 +51,9 @@ final class PreferencesSidebarModel: ObservableObject { .sink { [weak self] in self?.refreshSections() } + .store(in: &cancellables) + + setupVPNPaneVisibility() } @MainActor @@ -57,7 +63,7 @@ final class PreferencesSidebarModel: ObservableObject { includeDuckPlayer: Bool ) { let loadSections = { - let includingVPN = DefaultNetworkProtectionVisibility().isEnabled + let includingVPN = DefaultNetworkProtectionVisibility().isOnboarded return PreferencesSection.defaultSections(includingDuckPlayer: includeDuckPlayer, includingVPN: includingVPN) } @@ -67,6 +73,25 @@ final class PreferencesSidebarModel: ObservableObject { privacyConfigurationManager: privacyConfigurationManager) } + // MARK: - Setup + + private func setupVPNPaneVisibility() { + DefaultNetworkProtectionVisibility().onboardStatusPublisher + .receive(on: DispatchQueue.main) + .sink { [weak self] onboardingStatus in + guard let self else { return } + + if onboardingStatus != .completed && self.selectedPane == .vpn { + self.selectedPane = .general + } + + self.refreshSections() + } + .store(in: &cancellables) + } + + // MARK: - Refreshing logic + func refreshSections() { sections = loadSections() if !sections.flatMap(\.panes).contains(selectedPane), let firstPane = sections.first?.panes.first { @@ -89,5 +114,5 @@ final class PreferencesSidebarModel: ObservableObject { } private let loadSections: () -> [PreferencesSection] - private var privacyConfigCancellable: AnyCancellable? + private var cancellables = Set() } diff --git a/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift b/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift index 0e7b2782db..351e775e1f 100644 --- a/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift +++ b/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift @@ -68,8 +68,6 @@ final class NetworkProtectionFeatureDisabler: NetworkProtectionFeatureDisabling // Allow some time for the login items to fully launch try? await Task.sleep(interval: 0.5) - unpinNetworkProtection() - if uninstallSystemExtension { await removeSystemExtension() } @@ -86,6 +84,8 @@ final class NetworkProtectionFeatureDisabler: NetworkProtectionFeatureDisabling if !keepAuthToken { try? removeAppAuthToken() } + + unpinNetworkProtection() } } diff --git a/DuckDuckGo/Waitlist/NetworkProtectionFeatureVisibility.swift b/DuckDuckGo/Waitlist/NetworkProtectionFeatureVisibility.swift index f2c613d7a5..849ac169e2 100644 --- a/DuckDuckGo/Waitlist/NetworkProtectionFeatureVisibility.swift +++ b/DuckDuckGo/Waitlist/NetworkProtectionFeatureVisibility.swift @@ -19,6 +19,7 @@ #if NETWORK_PROTECTION import BrowserServicesKit +import Combine import Common import NetworkExtension import NetworkProtection @@ -36,6 +37,7 @@ struct DefaultNetworkProtectionVisibility: NetworkProtectionFeatureVisibility { private let networkProtectionFeatureActivation: NetworkProtectionFeatureActivation private let networkProtectionWaitlist = NetworkProtectionWaitlist() private let privacyConfigurationManager: PrivacyConfigurationManaging + private let defaults: UserDefaults var waitlistIsOngoing: Bool { isWaitlistEnabled && isWaitlistBetaActive @@ -45,12 +47,14 @@ struct DefaultNetworkProtectionVisibility: NetworkProtectionFeatureVisibility { networkProtectionFeatureActivation: NetworkProtectionFeatureActivation = NetworkProtectionKeychainTokenStore(), featureOverrides: WaitlistBetaOverriding = DefaultWaitlistBetaOverrides(), featureDisabler: NetworkProtectionFeatureDisabling = NetworkProtectionFeatureDisabler(), + defaults: UserDefaults = .shared, log: OSLog = .networkProtection) { self.privacyConfigurationManager = privacyConfigurationManager self.networkProtectionFeatureActivation = networkProtectionFeatureActivation self.featureDisabler = featureDisabler self.featureOverrides = featureOverrides + self.defaults = defaults } /// Calculates whether Network Protection is visible. @@ -64,8 +68,16 @@ struct DefaultNetworkProtectionVisibility: NetworkProtectionFeatureVisibility { isEasterEggUser || waitlistIsOngoing } - var isEnabled: Bool { - isEasterEggUser || (waitlistIsOngoing && isInvitedWaitlistUser) + /// Whether the user is fully onboarded + /// + var isOnboarded: Bool { + defaults.networkProtectionOnboardingStatus == .completed + } + + /// A publisher for the onboarding status + /// + var onboardStatusPublisher: AnyPublisher { + defaults.networkProtectionOnboardingStatusPublisher } /// Easter egg users can be identified by them being internal users and having an auth token (NetP being activated). From 79ae5729166879815acb83f2394ae35adaff74de Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Thu, 23 Nov 2023 15:04:09 +0100 Subject: [PATCH 32/40] Fixes the VPN uninstall error handling so that it won't uninstall if the user cancel's the auth dialog --- .../NetworkProtectionDebugMenu.swift | 2 +- .../NetworkProtectionDebugUtilities.swift | 8 +++---- .../NetworkProtectionFeatureDisabler.swift | 18 +++++++++----- .../TunnelControllerIPCService.swift | 24 +++++++------------ .../TunnelControllerIPCClient.swift | 16 ++++++++----- .../TunnelControllerIPCServer.swift | 20 +++++++++++----- 6 files changed, 49 insertions(+), 39 deletions(-) diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift index 1b2831a993..42178fc720 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift @@ -263,7 +263,7 @@ final class NetworkProtectionDebugMenu: NSMenu { /// @objc func expireRegistrationKeyNow(_ sender: Any?) { Task { - await debugUtilities.expireRegistrationKeyNow() + try? await debugUtilities.expireRegistrationKeyNow() } } diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift index bbef6a2ec6..610ea2bbe2 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift @@ -69,16 +69,16 @@ final class NetworkProtectionDebugUtilities { } func removeSystemExtensionAndAgents() async throws { - await networkProtectionFeatureDisabler.removeSystemExtension() + try await networkProtectionFeatureDisabler.removeSystemExtension() networkProtectionFeatureDisabler.disableLoginItems() } func sendTestNotificationRequest() async throws { - await ipcClient.debugCommand(.sendTestNotification) + try await ipcClient.debugCommand(.sendTestNotification) } - func expireRegistrationKeyNow() async { - await ipcClient.debugCommand(.expireRegistrationKey) + func expireRegistrationKeyNow() async throws { + try await ipcClient.debugCommand(.expireRegistrationKey) } } diff --git a/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift b/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift index 351e775e1f..abb22dd193 100644 --- a/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift +++ b/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift @@ -69,10 +69,15 @@ final class NetworkProtectionFeatureDisabler: NetworkProtectionFeatureDisabling try? await Task.sleep(interval: 0.5) if uninstallSystemExtension { - await removeSystemExtension() + do { + try await removeSystemExtension() + } catch { + // If there's an error uninstalling the extension, bail out. + return + } } - await removeVPNConfiguration() + try? await removeVPNConfiguration() // We want to give some time for the login item to reset state before disabling it try? await Task.sleep(interval: 0.5) @@ -97,8 +102,8 @@ final class NetworkProtectionFeatureDisabler: NetworkProtectionFeatureDisabling loginItemsManager.disableLoginItems(LoginItemsManager.networkProtectionLoginItems) } - func removeSystemExtension() async { - await ipcClient.debugCommand(.removeSystemExtension) + func removeSystemExtension() async throws { + try await ipcClient.debugCommand(.removeSystemExtension) } private func unpinNetworkProtection() { @@ -109,11 +114,12 @@ final class NetworkProtectionFeatureDisabler: NetworkProtectionFeatureDisabling try NetworkProtectionKeychainTokenStore().deleteToken() } - private func removeVPNConfiguration() async { + private func removeVPNConfiguration() async throws { // Remove the agent VPN configuration - await ipcClient.debugCommand(.removeVPNConfiguration) + try await ipcClient.debugCommand(.removeVPNConfiguration) // Remove the legacy (local) configuration + // We don't care if this fails let tunnels = try? await NETunnelProviderManager.loadAllFromPreferences() if let tunnels = tunnels { diff --git a/DuckDuckGoVPN/TunnelControllerIPCService.swift b/DuckDuckGoVPN/TunnelControllerIPCService.swift index 3a2e8ee658..febee3cff8 100644 --- a/DuckDuckGoVPN/TunnelControllerIPCService.swift +++ b/DuckDuckGoVPN/TunnelControllerIPCService.swift @@ -111,26 +111,14 @@ extension TunnelControllerIPCService: IPCServerInterface { try? await networkExtensionController.deactivateSystemExtension() } - func debugCommand(_ command: DebugCommand) async { - if let activeSession = try? await ConnectionSessionUtilities.activeSession(networkExtensionBundleID: Bundle.main.networkExtensionBundleID) { - - // First give a chance to the extension to process the command, since some commands - // may remove the VPN configuration or deactivate the extension. - try? await activeSession.sendProviderRequest(.debugCommand(command)) - } + func debugCommand(_ command: DebugCommand) async throws { + let activeSession = try await ConnectionSessionUtilities.activeSession(networkExtensionBundleID: Bundle.main.networkExtensionBundleID) switch command { case .removeSystemExtension: - await VPNConfigurationManager().removeVPNConfiguration() - defaults.networkProtectionOnboardingStatus = .isOnboarding(step: .userNeedsToAllowVPNConfiguration) - #if NETP_SYSTEM_EXTENSION - do { - try await networkExtensionController.deactivateSystemExtension() - defaults.networkProtectionOnboardingStatus = .default - } catch { - // No-op: for now we're not handling this type of error. - } + try await networkExtensionController.deactivateSystemExtension() + defaults.networkProtectionOnboardingStatus = .isOnboarding(step: .userNeedsToAllowExtension) #endif case .expireRegistrationKey: // Intentional no-op: handled by the extension @@ -140,6 +128,10 @@ extension TunnelControllerIPCService: IPCServerInterface { break case .removeVPNConfiguration: await VPNConfigurationManager().removeVPNConfiguration() + + if defaults.networkProtectionOnboardingStatus == .completed { + defaults.networkProtectionOnboardingStatus = .isOnboarding(step: .userNeedsToAllowVPNConfiguration) + } } } } diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionIPC/TunnelControllerIPCClient.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionIPC/TunnelControllerIPCClient.swift index dd34206618..92ec6e6425 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionIPC/TunnelControllerIPCClient.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionIPC/TunnelControllerIPCClient.swift @@ -95,20 +95,24 @@ extension TunnelControllerIPCClient: IPCServerInterface { }) } - public func debugCommand(_ command: DebugCommand) async { + public func debugCommand(_ command: DebugCommand) async throws { guard let payload = try? JSONEncoder().encode(command) else { return } - await withCheckedContinuation { continuation in + try await withCheckedThrowingContinuation { (continuation: CheckedContinuation) in xpc.execute(call: { server in - server.debugCommand(payload) { - continuation.resume() + server.debugCommand(payload) { error in + if let error { + continuation.resume(throwing: error) + } else { + continuation.resume() + } } - }, xpcReplyErrorHandler: { _ in + }, xpcReplyErrorHandler: { error in // Intentional no-op as there's no completion block // If you add a completion block, please remember to call it here too! - continuation.resume() + continuation.resume(throwing: error) }) } } diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionIPC/TunnelControllerIPCServer.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionIPC/TunnelControllerIPCServer.swift index 8ef52836e8..3fe62c74f3 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionIPC/TunnelControllerIPCServer.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionIPC/TunnelControllerIPCServer.swift @@ -39,7 +39,7 @@ public protocol IPCServerInterface: AnyObject { /// Debug commands /// - func debugCommand(_ command: DebugCommand) async + func debugCommand(_ command: DebugCommand) async throws } /// This protocol describes the server-side XPC interface. @@ -65,12 +65,16 @@ protocol XPCServerInterface { /// Debug commands /// - func debugCommand(_ payload: Data, completion: @escaping () -> Void) + func debugCommand(_ payload: Data, completion: @escaping (Error?) -> Void) } public final class TunnelControllerIPCServer { let xpc: XPCServer + enum IPCError: Error { + case cannotDecodeDebugCommand + } + /// The delegate. /// public weak var serverDelegate: IPCServerInterface? @@ -148,15 +152,19 @@ extension TunnelControllerIPCServer: XPCServerInterface { serverDelegate?.stop() } - func debugCommand(_ payload: Data, completion: @escaping () -> Void) { + func debugCommand(_ payload: Data, completion: @escaping (Error?) -> Void) { guard let command = try? JSONDecoder().decode(DebugCommand.self, from: payload) else { - completion() + completion(IPCError.cannotDecodeDebugCommand) return } Task { - await serverDelegate?.debugCommand(command) - completion() + do { + try await serverDelegate?.debugCommand(command) + completion(nil) + } catch { + completion(error) + } } } } From 4ce92e63e6aa1d0d41f8a95fe3c74fcbd646cc09 Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Thu, 23 Nov 2023 16:46:59 +0100 Subject: [PATCH 33/40] Uninstalling NetP now shows a confirmation bubble --- .../PopoverMessageViewController.swift | 13 +++- .../View/NavigationBar.storyboard | 5 +- .../View/NavigationBarViewController.swift | 16 ++++- .../NetworkProtectionDebugUtilities.swift | 9 ++- .../Model/VPNPreferencesModel.swift | 24 +++---- .../Preferences/View/PreferencesVPNView.swift | 4 +- .../NetworkProtectionFeatureDisabler.swift | 67 ++++++++++--------- .../NetworkProtectionFeatureVisibility.swift | 8 ++- 8 files changed, 93 insertions(+), 53 deletions(-) diff --git a/DuckDuckGo/MessageViews/PopoverMessageViewController.swift b/DuckDuckGo/MessageViews/PopoverMessageViewController.swift index 2efe639f1d..0609d8425a 100644 --- a/DuckDuckGo/MessageViews/PopoverMessageViewController.swift +++ b/DuckDuckGo/MessageViews/PopoverMessageViewController.swift @@ -63,6 +63,17 @@ final class PopoverMessageViewController: NSHostingController - + - + @@ -365,6 +365,7 @@ + diff --git a/DuckDuckGo/NavigationBar/View/NavigationBarViewController.swift b/DuckDuckGo/NavigationBar/View/NavigationBarViewController.swift index a7828f9bca..048f491f7c 100644 --- a/DuckDuckGo/NavigationBar/View/NavigationBarViewController.swift +++ b/DuckDuckGo/NavigationBar/View/NavigationBarViewController.swift @@ -43,6 +43,7 @@ final class NavigationBarViewController: NSViewController { @IBOutlet weak var goBackButton: NSButton! @IBOutlet weak var goForwardButton: NSButton! @IBOutlet weak var refreshOrStopButton: NSButton! + @IBOutlet weak var menuButtons: NSStackView! @IBOutlet weak var optionsButton: NSButton! @IBOutlet weak var bookmarkListButton: MouseOverButton! @IBOutlet weak var passwordManagementButton: MouseOverButton! @@ -418,6 +419,20 @@ final class NavigationBarViewController: NSViewController { selector: #selector(showAutoconsentFeedback(_:)), name: AutoconsentUserScript.Constants.newSitePopupHidden, object: nil) + + NotificationCenter.default.addObserver(self, + selector: #selector(showVPNUninstalledFeedback(_:)), + name: Notification.Name("com.duckduckgo.NetworkProtection.uninstalled"), + object: nil) + } + + @objc private func showVPNUninstalledFeedback(_ sender: Notification) { + guard view.window?.isKeyWindow == true else { return } + + DispatchQueue.main.async { + let viewController = PopoverMessageViewController(message: "Network Protection was uninstalled") + viewController.show(onParent: self, rect: self.optionsButton.frame, of: self.menuButtons) + } } @objc private func showPrivateEmailCopiedToClipboard(_ sender: Notification) { @@ -427,7 +442,6 @@ final class NavigationBarViewController: NSViewController { let viewController = PopoverMessageViewController(message: UserText.privateEmailCopiedToClipboard) viewController.show(onParent: self, relativeTo: self.optionsButton) } - } @objc private func showFireproofingFeedback(_ sender: Notification) { diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift index 610ea2bbe2..df07768a36 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift @@ -56,9 +56,14 @@ final class NetworkProtectionDebugUtilities { // MARK: - Debug commands for the extension - func resetAllState(keepAuthToken: Bool) async throws { + func resetAllState(keepAuthToken: Bool) async { + let uninstalledSuccessfully = await networkProtectionFeatureDisabler.disable(keepAuthToken: keepAuthToken, uninstallSystemExtension: true) + + guard uninstalledSuccessfully else { + return + } + settings.resetToDefaults() - networkProtectionFeatureDisabler.disable(keepAuthToken: keepAuthToken, uninstallSystemExtension: true) NetworkProtectionWaitlist().waitlistStorage.deleteWaitlistState() DefaultWaitlistActivationDateStore().removeDates() diff --git a/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift b/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift index 0929589430..24ceabbecb 100644 --- a/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift +++ b/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift @@ -83,20 +83,16 @@ final class VPNPreferencesModel: ObservableObject { .store(in: &cancellables) } - func uninstallVPN() { - Task { @MainActor in - let response = await uninstallVPNConfirmationAlert().runModal() - - switch response { - case .OK: - NetworkProtectionFeatureDisabler().disable(keepAuthToken: true, uninstallSystemExtension: true) - case .cancel: - // intentional no-op - break - default: - // intentional no-op - break - } + @MainActor + func uninstallVPN() async { + let response = await uninstallVPNConfirmationAlert().runModal() + + switch response { + case .OK: + await NetworkProtectionFeatureDisabler().disable(keepAuthToken: true, uninstallSystemExtension: true) + default: + // intentional no-op + break } } diff --git a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift index 735115de73..48eb9ae338 100644 --- a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift +++ b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift @@ -91,7 +91,9 @@ extension Preferences { if model.showUninstallVPN { PreferencePaneSection { Button(UserText.uninstallVPNButtonTitle) { - model.uninstallVPN() + Task { @MainActor in + await model.uninstallVPN() + } } } } diff --git a/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift b/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift index abb22dd193..323b0527c0 100644 --- a/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift +++ b/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift @@ -27,7 +27,9 @@ import NetworkProtectionUI import SystemExtensions protocol NetworkProtectionFeatureDisabling { - func disable(keepAuthToken: Bool, uninstallSystemExtension: Bool) + /// - Returns: `true` if the uninstallation was completed. `false` if it was cancelled by the user or an error. + /// + func disable(keepAuthToken: Bool, uninstallSystemExtension: Bool) async -> Bool } final class NetworkProtectionFeatureDisabler: NetworkProtectionFeatureDisabling { @@ -59,39 +61,36 @@ final class NetworkProtectionFeatureDisabler: NetworkProtectionFeatureDisabling /// - keepAuthToken: If `true`, the auth token will not be removed. /// - includeSystemExtension: Whether this method should uninstall the system extension. /// - func disable(keepAuthToken: Bool, uninstallSystemExtension: Bool) { - Task { - // To disable NetP we need the login item to be running - // This should be fine though as we'll disable them further down below - enableLoginItems() - - // Allow some time for the login items to fully launch - try? await Task.sleep(interval: 0.5) - - if uninstallSystemExtension { - do { - try await removeSystemExtension() - } catch { - // If there's an error uninstalling the extension, bail out. - return - } + @discardableResult + func disable(keepAuthToken: Bool, uninstallSystemExtension: Bool) async -> Bool { + // To disable NetP we need the login item to be running + // This should be fine though as we'll disable them further down below + enableLoginItems() + + // Allow some time for the login items to fully launch + try? await Task.sleep(interval: 0.5) + + if uninstallSystemExtension { + do { + try await removeSystemExtension() + } catch { + return false } + } - try? await removeVPNConfiguration() - - // We want to give some time for the login item to reset state before disabling it - try? await Task.sleep(interval: 0.5) - - disableLoginItems() - - resetUserDefaults() + try? await removeVPNConfiguration() + // We want to give some time for the login item to reset state before disabling it + try? await Task.sleep(interval: 0.5) + disableLoginItems() + resetUserDefaults() - if !keepAuthToken { - try? removeAppAuthToken() - } - - unpinNetworkProtection() + if !keepAuthToken { + try? removeAppAuthToken() } + + unpinNetworkProtection() + postVPNUninstalledNotification() + return true } private func enableLoginItems() { @@ -133,6 +132,14 @@ final class NetworkProtectionFeatureDisabler: NetworkProtectionFeatureDisabling private func resetUserDefaults() { settings.resetToDefaults() } + + private func postVPNUninstalledNotification() { + DispatchQueue.main.async { + NotificationCenter.default.post( + name: NSNotification.Name(rawValue: "com.duckduckgo.NetworkProtection.uninstalled"), + object: nil) + } + } } #endif diff --git a/DuckDuckGo/Waitlist/NetworkProtectionFeatureVisibility.swift b/DuckDuckGo/Waitlist/NetworkProtectionFeatureVisibility.swift index 849ac169e2..50dafce2e3 100644 --- a/DuckDuckGo/Waitlist/NetworkProtectionFeatureVisibility.swift +++ b/DuckDuckGo/Waitlist/NetworkProtectionFeatureVisibility.swift @@ -130,7 +130,9 @@ struct DefaultNetworkProtectionVisibility: NetworkProtectionFeatureVisibility { } func disableForAllUsers() { - featureDisabler.disable(keepAuthToken: false, uninstallSystemExtension: false) + Task { + await featureDisabler.disable(keepAuthToken: false, uninstallSystemExtension: false) + } } func disableForWaitlistUsers() { @@ -138,7 +140,9 @@ struct DefaultNetworkProtectionVisibility: NetworkProtectionFeatureVisibility { return } - featureDisabler.disable(keepAuthToken: false, uninstallSystemExtension: false) + Task { + await featureDisabler.disable(keepAuthToken: false, uninstallSystemExtension: false) + } } } From 4706c7cf3643378f3e2981bb365826a282ea8c14 Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Thu, 23 Nov 2023 17:10:12 +0100 Subject: [PATCH 34/40] Fixes some final issues --- DuckDuckGo/NavigationBar/View/NavigationBar.storyboard | 5 ++--- .../NavigationBar/View/NavigationBarViewController.swift | 5 ++--- DuckDuckGo/Preferences/View/PreferencesVPNView.swift | 2 +- .../Waitlist/NetworkProtectionFeatureDisabler.swift | 9 +++++++-- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/DuckDuckGo/NavigationBar/View/NavigationBar.storyboard b/DuckDuckGo/NavigationBar/View/NavigationBar.storyboard index 09031f9073..c13932d168 100644 --- a/DuckDuckGo/NavigationBar/View/NavigationBar.storyboard +++ b/DuckDuckGo/NavigationBar/View/NavigationBar.storyboard @@ -1,7 +1,7 @@ - + - + @@ -365,7 +365,6 @@ - diff --git a/DuckDuckGo/NavigationBar/View/NavigationBarViewController.swift b/DuckDuckGo/NavigationBar/View/NavigationBarViewController.swift index 048f491f7c..9b581cae94 100644 --- a/DuckDuckGo/NavigationBar/View/NavigationBarViewController.swift +++ b/DuckDuckGo/NavigationBar/View/NavigationBarViewController.swift @@ -43,7 +43,6 @@ final class NavigationBarViewController: NSViewController { @IBOutlet weak var goBackButton: NSButton! @IBOutlet weak var goForwardButton: NSButton! @IBOutlet weak var refreshOrStopButton: NSButton! - @IBOutlet weak var menuButtons: NSStackView! @IBOutlet weak var optionsButton: NSButton! @IBOutlet weak var bookmarkListButton: MouseOverButton! @IBOutlet weak var passwordManagementButton: MouseOverButton! @@ -422,7 +421,7 @@ final class NavigationBarViewController: NSViewController { NotificationCenter.default.addObserver(self, selector: #selector(showVPNUninstalledFeedback(_:)), - name: Notification.Name("com.duckduckgo.NetworkProtection.uninstalled"), + name: NetworkProtectionFeatureDisabler.vpnUninstalledNotificationName, object: nil) } @@ -431,7 +430,7 @@ final class NavigationBarViewController: NSViewController { DispatchQueue.main.async { let viewController = PopoverMessageViewController(message: "Network Protection was uninstalled") - viewController.show(onParent: self, rect: self.optionsButton.frame, of: self.menuButtons) + viewController.show(onParent: self, relativeTo: self.optionsButton) } } diff --git a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift index 48eb9ae338..cb16728d5c 100644 --- a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift +++ b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift @@ -74,7 +74,7 @@ extension Preferences { }.frame(alignment: .topLeading) .frame(idealWidth: .infinity, maxWidth: .infinity) .padding(10) - .background(Color("BlackWhite10")) + .background(Color("BlackWhite1")) .roundedBorder() } diff --git a/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift b/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift index 323b0527c0..af14766797 100644 --- a/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift +++ b/DuckDuckGo/Waitlist/NetworkProtectionFeatureDisabler.swift @@ -33,6 +33,8 @@ protocol NetworkProtectionFeatureDisabling { } final class NetworkProtectionFeatureDisabler: NetworkProtectionFeatureDisabling { + static let vpnUninstalledNotificationName = NSNotification.Name(rawValue: "com.duckduckgo.NetworkProtection.uninstalled") + private let log: OSLog private let loginItemsManager: LoginItemsManager private let pinningManager: LocalPinningManager @@ -134,9 +136,12 @@ final class NetworkProtectionFeatureDisabler: NetworkProtectionFeatureDisabling } private func postVPNUninstalledNotification() { - DispatchQueue.main.async { + Task { @MainActor in + // Wait a bit since the NetP button is likely being hidden + try? await Task.sleep(nanoseconds: 500 * NSEC_PER_MSEC) + NotificationCenter.default.post( - name: NSNotification.Name(rawValue: "com.duckduckgo.NetworkProtection.uninstalled"), + name: Self.vpnUninstalledNotificationName, object: nil) } } From 206985de3bef7fb4f3b1657af4dd146c55e4a503 Mon Sep 17 00:00:00 2001 From: Sam Symons Date: Mon, 27 Nov 2023 14:05:11 -0800 Subject: [PATCH 35/40] Fix merge issues and sandboxed build compilation. --- DuckDuckGo.xcodeproj/project.pbxproj | 51 +++++++++++-------- .../xcshareddata/swiftpm/Package.resolved | 4 +- .../DBP/LoginItem+DataBrokerProtection.swift | 2 +- .../View/NavigationBarViewController.swift | 2 + .../Model/PreferencesSection.swift | 8 +++ .../Model/PreferencesSidebarModel.swift | 8 +++ .../Model/VPNPreferencesModel.swift | 4 ++ .../View/PreferencesRootView.swift | 4 ++ .../Preferences/View/PreferencesVPNView.swift | 4 ++ .../View/PreferencesViewController.swift | 3 ++ 10 files changed, 67 insertions(+), 23 deletions(-) diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 5dd35362b5..77cf372873 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -1107,6 +1107,15 @@ 4B3F641E27A8D3BD00E0C118 /* BrowserProfileTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B3F641D27A8D3BD00E0C118 /* BrowserProfileTests.swift */; }; 4B4032842AAAC24400CCA602 /* WaitlistActivationDateStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B4032832AAAC24400CCA602 /* WaitlistActivationDateStore.swift */; }; 4B4032852AAAC24400CCA602 /* WaitlistActivationDateStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B4032832AAAC24400CCA602 /* WaitlistActivationDateStore.swift */; }; + 4B41EDA02B15437A001EEDF4 /* NetworkProtectionNotificationsPresenterFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B41ED9F2B15437A001EEDF4 /* NetworkProtectionNotificationsPresenterFactory.swift */; }; + 4B41EDA12B15437A001EEDF4 /* NetworkProtectionNotificationsPresenterFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B41ED9F2B15437A001EEDF4 /* NetworkProtectionNotificationsPresenterFactory.swift */; }; + 4B41EDA32B1543B9001EEDF4 /* VPNPreferencesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B41EDA22B1543B9001EEDF4 /* VPNPreferencesModel.swift */; }; + 4B41EDA42B1543B9001EEDF4 /* VPNPreferencesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B41EDA22B1543B9001EEDF4 /* VPNPreferencesModel.swift */; }; + 4B41EDA52B1543B9001EEDF4 /* VPNPreferencesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B41EDA22B1543B9001EEDF4 /* VPNPreferencesModel.swift */; }; + 4B41EDA72B1543C9001EEDF4 /* PreferencesVPNView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B41EDA62B1543C9001EEDF4 /* PreferencesVPNView.swift */; }; + 4B41EDA82B1543C9001EEDF4 /* PreferencesVPNView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B41EDA62B1543C9001EEDF4 /* PreferencesVPNView.swift */; }; + 4B41EDA92B1543C9001EEDF4 /* PreferencesVPNView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B41EDA62B1543C9001EEDF4 /* PreferencesVPNView.swift */; }; + 4B41EDAB2B1544B2001EEDF4 /* LoginItems in Frameworks */ = {isa = PBXBuildFile; productRef = 4B41EDAA2B1544B2001EEDF4 /* LoginItems */; }; 4B434690285ED7A100177407 /* BookmarksBarViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B43468F285ED7A100177407 /* BookmarksBarViewModelTests.swift */; }; 4B43469528655D1400177407 /* FirefoxDataImporterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B43469428655D1400177407 /* FirefoxDataImporterTests.swift */; }; 4B4BEC3D2A11B56B001D9AC5 /* DuckDuckGoNotificationsAppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B4BEC382A11B509001D9AC5 /* DuckDuckGoNotificationsAppDelegate.swift */; }; @@ -1339,7 +1348,6 @@ 4B9579A32AC7AE700062CA31 /* PopUpButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BBE0AA627B9B027003B37A8 /* PopUpButton.swift */; }; 4B9579A42AC7AE700062CA31 /* NetworkProtectionInviteDialog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B4D606C2A0B29FA00BCD287 /* NetworkProtectionInviteDialog.swift */; }; 4B9579A52AC7AE700062CA31 /* SuggestionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AABEE6A424AA0A7F0043105B /* SuggestionViewController.swift */; }; - 4B9579A62AC7AE700062CA31 /* NetworkProtectionUserDefaultsConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F92BA42A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift */; }; 4B9579A72AC7AE700062CA31 /* AddEditFavoriteWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85589E7A27BBB8620038AD11 /* AddEditFavoriteWindow.swift */; }; 4B9579A82AC7AE700062CA31 /* BWKeyStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D6216B129069BBF00386B2C /* BWKeyStorage.swift */; }; 4B9579A92AC7AE700062CA31 /* VisitViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA7E919E287872EA00AB6B62 /* VisitViewModel.swift */; }; @@ -2902,13 +2910,6 @@ B6F7128229F6820A00594A45 /* QuickLookUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6F7128029F681EB00594A45 /* QuickLookUI.framework */; }; B6F92BA22A691580002ABA6B /* UserDefaultsWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85C6A29525CC1FFD00EEB5F1 /* UserDefaultsWrapper.swift */; }; B6F92BA32A691583002ABA6B /* UserDefaultsWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85C6A29525CC1FFD00EEB5F1 /* UserDefaultsWrapper.swift */; }; - B6F92BA52A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F92BA42A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift */; }; - B6F92BA62A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F92BA42A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift */; }; - B6F92BA72A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F92BA42A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift */; }; - B6F92BA82A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F92BA42A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift */; }; - B6F92BA92A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F92BA42A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift */; }; - B6F92BAA2A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F92BA42A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift */; }; - B6F92BAB2A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F92BA42A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift */; }; B6F92BAC2A6937B3002ABA6B /* OptionalExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = B637273C26CCF0C200C8CB02 /* OptionalExtension.swift */; }; B6F92BAD2A6937B5002ABA6B /* OptionalExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = B637273C26CCF0C200C8CB02 /* OptionalExtension.swift */; }; B6FA893D269C423100588ECD /* PrivacyDashboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B6FA893C269C423100588ECD /* PrivacyDashboard.storyboard */; }; @@ -3325,6 +3326,9 @@ 4B3B848F297A0E1000A384BD /* EmailManagerExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmailManagerExtension.swift; sourceTree = ""; }; 4B3F641D27A8D3BD00E0C118 /* BrowserProfileTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserProfileTests.swift; sourceTree = ""; }; 4B4032832AAAC24400CCA602 /* WaitlistActivationDateStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaitlistActivationDateStore.swift; sourceTree = ""; }; + 4B41ED9F2B15437A001EEDF4 /* NetworkProtectionNotificationsPresenterFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkProtectionNotificationsPresenterFactory.swift; sourceTree = ""; }; + 4B41EDA22B1543B9001EEDF4 /* VPNPreferencesModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VPNPreferencesModel.swift; sourceTree = ""; }; + 4B41EDA62B1543C9001EEDF4 /* PreferencesVPNView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreferencesVPNView.swift; sourceTree = ""; }; 4B43468F285ED7A100177407 /* BookmarksBarViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarksBarViewModelTests.swift; sourceTree = ""; }; 4B43469428655D1400177407 /* FirefoxDataImporterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirefoxDataImporterTests.swift; sourceTree = ""; }; 4B4BEC182A11B3EA001D9AC5 /* DuckDuckGoNotifications.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = DuckDuckGoNotifications.xcconfig; sourceTree = ""; }; @@ -4165,7 +4169,6 @@ B6F56566299A414300A04298 /* WKWebViewMockingExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WKWebViewMockingExtension.swift; sourceTree = ""; }; B6F7127D29F6779000594A45 /* QRSharingService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRSharingService.swift; sourceTree = ""; }; B6F7128029F681EB00594A45 /* QuickLookUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickLookUI.framework; path = System/Library/Frameworks/QuickLookUI.framework; sourceTree = SDKROOT; }; - B6F92BA42A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionUserDefaultsConstants.swift; sourceTree = ""; }; B6FA893C269C423100588ECD /* PrivacyDashboard.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = PrivacyDashboard.storyboard; sourceTree = ""; }; B6FA893E269C424500588ECD /* PrivacyDashboardViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacyDashboardViewController.swift; sourceTree = ""; }; B6FA8940269C425400588ECD /* PrivacyDashboardPopover.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacyDashboardPopover.swift; sourceTree = ""; }; @@ -4265,6 +4268,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 4B41EDAB2B1544B2001EEDF4 /* LoginItems in Frameworks */, 7BEEA5122AD1235B00A9E72B /* NetworkProtectionIPC in Frameworks */, 7BA7CC5F2AD1210C0042E5CE /* Networking in Frameworks */, 7BEEA5162AD1236E00A9E72B /* NetworkProtectionUI in Frameworks */, @@ -4842,6 +4846,7 @@ 3776582E27F82E62009A6B35 /* AutofillPreferences.swift */, 37CD54C327F2FDD100F1F7B9 /* DownloadsPreferences.swift */, 37CD54C527F2FDD100F1F7B9 /* AboutModel.swift */, + 4B41EDA22B1543B9001EEDF4 /* VPNPreferencesModel.swift */, ); path = Model; sourceTree = ""; @@ -4936,6 +4941,7 @@ 379DE4BC27EA31AC002CC3DE /* PreferencesAutofillView.swift */, 37CC53EF27E8D1440028713D /* PreferencesDownloadsView.swift */, 37AFCE9127DB8CAD00471A10 /* PreferencesAboutView.swift */, + 4B41EDA62B1543C9001EEDF4 /* PreferencesVPNView.swift */, ); path = View; sourceTree = ""; @@ -5173,6 +5179,7 @@ 4B4D607D2A0B29FA00BCD287 /* NetworkExtensionTargets */ = { isa = PBXGroup; children = ( + 4B41ED9F2B15437A001EEDF4 /* NetworkProtectionNotificationsPresenterFactory.swift */, EEF12E6D2A2111880023E6BF /* MacPacketTunnelProvider.swift */, ); path = NetworkExtensionTargets; @@ -7834,7 +7841,6 @@ children = ( EEAD7A6E2A1D3E1F002A24E7 /* AppLauncher.swift */, 4BF0E5042AD2551A00FFEC9E /* NetworkProtectionPixelEvent.swift */, - B6F92BA42A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift */, 7B934C402A866DD400FC8F9C /* UserDefaults+NetworkProtectionShared.swift */, 7BFE95532A9DF2930081ABE9 /* UserDefaults+NetworkProtectionWaitlist.swift */, ); @@ -8003,6 +8009,7 @@ 7BEEA5152AD1236E00A9E72B /* NetworkProtectionUI */, 7BEC182E2AD5D8DC00D30536 /* SystemExtensionManager */, 7BFCB74D2ADE7E1A00DA3EA7 /* PixelKit */, + 4B41EDAA2B1544B2001EEDF4 /* LoginItems */, ); productName = DuckDuckGoAgent; productReference = 4B2D06392A11CFBB00DE1F49 /* DuckDuckGo VPN.app */; @@ -9079,6 +9086,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4B41EDA82B1543C9001EEDF4 /* PreferencesVPNView.swift in Sources */, 3706FA7B293F65D500E42796 /* FaviconUserScript.swift in Sources */, 3706FA7E293F65D500E42796 /* LottieAnimationCache.swift in Sources */, 3706FA7F293F65D500E42796 /* TabIndex.swift in Sources */, @@ -9350,6 +9358,7 @@ B603971B29BA084C00902A34 /* JSAlertController.swift in Sources */, 3706FB6A293F65D500E42796 /* AddressBarButton.swift in Sources */, 3706FB6B293F65D500E42796 /* HistoryEntry.swift in Sources */, + 4B41EDA42B1543B9001EEDF4 /* VPNPreferencesModel.swift in Sources */, 3706FB6C293F65D500E42796 /* FaviconStore.swift in Sources */, 3706FB6D293F65D500E42796 /* SuggestionListCharacteristics.swift in Sources */, 377D801F2AB48191002AF251 /* FavoritesDisplayModeSyncHandler.swift in Sources */, @@ -9550,7 +9559,6 @@ B60C6F7829B0E286007BFAA8 /* SearchNonexistentDomainNavigationResponder.swift in Sources */, 3707C720294B5D2900682A9F /* WKWebsiteDataStoreExtension.swift in Sources */, 3706FC03293F65D500E42796 /* TabPreviewViewController.swift in Sources */, - B6F92BA62A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */, 4B9754EC2984300100D7B834 /* EmailManagerExtension.swift in Sources */, 3706FC04293F65D500E42796 /* PreferencesPrivacyView.swift in Sources */, 3706FC05293F65D500E42796 /* NSPasteboardExtension.swift in Sources */, @@ -10040,7 +10048,6 @@ B65DA5F42A77D3FA00CBEE8D /* BundleExtension.swift in Sources */, 4B2D062D2A11C12300DE1F49 /* Logging.swift in Sources */, 7B2E52252A5FEC09000C6D39 /* NetworkProtectionAgentNotificationsPresenter.swift in Sources */, - B6F92BA82A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */, B602E8232A1E260E006D261F /* Bundle+NetworkProtectionExtensions.swift in Sources */, EEAD7A7B2A1D3E20002A24E7 /* AppLauncher.swift in Sources */, 4B2D062A2A11C0C900DE1F49 /* NetworkProtectionOptionKeyExtension.swift in Sources */, @@ -10048,6 +10055,7 @@ 4B2D06322A11C1D300DE1F49 /* NSApplicationExtension.swift in Sources */, 4B2D06332A11C1E300DE1F49 /* OptionalExtension.swift in Sources */, 4BF0E50B2AD2552200FFEC9E /* NetworkProtectionPixelEvent.swift in Sources */, + 4B41EDA12B15437A001EEDF4 /* NetworkProtectionNotificationsPresenterFactory.swift in Sources */, 4B2537782A11C00F00610219 /* NetworkProtectionExtensionMachService.swift in Sources */, B65DA5F32A77D3C700CBEE8D /* UserDefaultsWrapper.swift in Sources */, 4B2537722A11BF8B00610219 /* main.swift in Sources */, @@ -10077,7 +10085,6 @@ 7BA7CC4A2AD11EA00042E5CE /* NetworkProtectionTunnelController.swift in Sources */, 7BD1688E2AD4A4C400D24876 /* NetworkExtensionController.swift in Sources */, 7BA7CC3E2AD11E380042E5CE /* TunnelControllerIPCService.swift in Sources */, - B6F92BAA2A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */, 7BA7CC402AD11E3D0042E5CE /* AppLauncher+DefaultInitializer.swift in Sources */, EEC589DB2A4F1CE700BCD60C /* AppLauncher.swift in Sources */, B65DA5EF2A77CC3A00CBEE8D /* Bundle+NetworkProtectionExtensions.swift in Sources */, @@ -10097,7 +10104,6 @@ B6F92BA32A691583002ABA6B /* UserDefaultsWrapper.swift in Sources */, 4B2D067C2A13340900DE1F49 /* Logging.swift in Sources */, B6F92BAD2A6937B5002ABA6B /* OptionalExtension.swift in Sources */, - B6F92BAB2A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */, 7BA7CC5A2AD120640042E5CE /* NetworkProtection+ConvenienceInitializers.swift in Sources */, 7BA7CC3B2AD11E330042E5CE /* Bundle+Configuration.swift in Sources */, EEC589DC2A4F1CE800BCD60C /* AppLauncher.swift in Sources */, @@ -10132,7 +10138,6 @@ B602E8222A1E2603006D261F /* Bundle+NetworkProtectionExtensions.swift in Sources */, B602E81A2A1E2570006D261F /* URL+NetworkProtection.swift in Sources */, 4B4BEC402A11B5B5001D9AC5 /* NetworkProtectionExtensionMachService.swift in Sources */, - B6F92BA92A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */, EEAD7A7C2A1D3E20002A24E7 /* AppLauncher.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -10141,6 +10146,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4B41EDA02B15437A001EEDF4 /* NetworkProtectionNotificationsPresenterFactory.swift in Sources */, 4B4D609F2A0B2C7300BCD287 /* Logging.swift in Sources */, 4B4D60A12A0B2D6100BCD287 /* NetworkProtectionOptionKeyExtension.swift in Sources */, B602E8182A1E2570006D261F /* URL+NetworkProtection.swift in Sources */, @@ -10152,7 +10158,6 @@ EEF12E6E2A2111880023E6BF /* MacPacketTunnelProvider.swift in Sources */, 4BF0E50C2AD2552300FFEC9E /* NetworkProtectionPixelEvent.swift in Sources */, 4B4D60AC2A0C804B00BCD287 /* OptionalExtension.swift in Sources */, - B6F92BA72A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */, B65DA5F22A77D3C600CBEE8D /* UserDefaultsWrapper.swift in Sources */, EEAD7A7A2A1D3E20002A24E7 /* AppLauncher.swift in Sources */, ); @@ -10261,7 +10266,6 @@ 4B9579A32AC7AE700062CA31 /* PopUpButton.swift in Sources */, 4B9579A42AC7AE700062CA31 /* NetworkProtectionInviteDialog.swift in Sources */, 4B9579A52AC7AE700062CA31 /* SuggestionViewController.swift in Sources */, - 4B9579A62AC7AE700062CA31 /* NetworkProtectionUserDefaultsConstants.swift in Sources */, 4B9579A72AC7AE700062CA31 /* AddEditFavoriteWindow.swift in Sources */, 4B9579A82AC7AE700062CA31 /* BWKeyStorage.swift in Sources */, 4B9579A92AC7AE700062CA31 /* VisitViewModel.swift in Sources */, @@ -10494,6 +10498,7 @@ 4B957A7F2AC7AE700062CA31 /* NSApplicationExtension.swift in Sources */, 4B957A802AC7AE700062CA31 /* NSWindowExtension.swift in Sources */, 4B957A812AC7AE700062CA31 /* KeychainType+ClientDefault.swift in Sources */, + 4B41EDA52B1543B9001EEDF4 /* VPNPreferencesModel.swift in Sources */, 4B957A822AC7AE700062CA31 /* SyncDebugMenu.swift in Sources */, 4B957A832AC7AE700062CA31 /* BookmarkPopover.swift in Sources */, 4B957A842AC7AE700062CA31 /* PreferencesDownloadsView.swift in Sources */, @@ -10601,6 +10606,7 @@ 4B957AE82AC7AE700062CA31 /* Permissions.xcdatamodeld in Sources */, 4B957AE92AC7AE700062CA31 /* JSAlertController.swift in Sources */, 4B957AEA2AC7AE700062CA31 /* NotificationService.swift in Sources */, + 4B41EDA92B1543C9001EEDF4 /* PreferencesVPNView.swift in Sources */, 4B957AEB2AC7AE700062CA31 /* SyncPreferences.swift in Sources */, 4B957AEC2AC7AE700062CA31 /* FaviconNullStore.swift in Sources */, 4B957AED2AC7AE700062CA31 /* PaddedImageButton.swift in Sources */, @@ -10990,7 +10996,6 @@ 4BBE0AA727B9B027003B37A8 /* PopUpButton.swift in Sources */, 4B4D60CF2A0C849600BCD287 /* NetworkProtectionInviteDialog.swift in Sources */, AABEE6A524AA0A7F0043105B /* SuggestionViewController.swift in Sources */, - B6F92BA52A691A44002ABA6B /* NetworkProtectionUserDefaultsConstants.swift in Sources */, 85589E8027BBB8630038AD11 /* AddEditFavoriteWindow.swift in Sources */, 1D6216B229069BBF00386B2C /* BWKeyStorage.swift in Sources */, AA7E919F287872EA00AB6B62 /* VisitViewModel.swift in Sources */, @@ -11302,6 +11307,7 @@ B693954B26F04BEB0015B914 /* MouseOverView.swift in Sources */, AAE7527C263B056C00B973F8 /* HistoryStore.swift in Sources */, AAE246F32709EF3B00BEEAEE /* FirePopoverCollectionViewItem.swift in Sources */, + 4B41EDA32B1543B9001EEDF4 /* VPNPreferencesModel.swift in Sources */, AA61C0D22727F59B00E6B681 /* ArrayExtension.swift in Sources */, 4B4D60CC2A0C849600BCD287 /* NetworkProtectionInviteCodeViewModel.swift in Sources */, AAC30A2C268F1ECD00D2D9CD /* CrashReportSender.swift in Sources */, @@ -11421,6 +11427,7 @@ 4B379C1527BD91E3008A968E /* QuartzIdleStateProvider.swift in Sources */, 37F19A6728E1B43200740DC6 /* DuckPlayerPreferences.swift in Sources */, B6C0B22E26E61CE70031CB7F /* DownloadViewModel.swift in Sources */, + 4B41EDA72B1543C9001EEDF4 /* PreferencesVPNView.swift in Sources */, 373A1AA8283ED1B900586521 /* BookmarkHTMLReader.swift in Sources */, B68458B825C7E8B200DC17B6 /* Tab+NSSecureCoding.swift in Sources */, 85378DA0274E6F42007C5CBF /* NSNotificationName+EmailManager.swift in Sources */, @@ -12725,8 +12732,8 @@ isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit"; requirement = { - kind = exactVersion; - version = 85.1.1; + branch = "diego/vpn-settings"; + kind = branch; }; }; AA06B6B52672AF8100F541C5 /* XCRemoteSwiftPackageReference "Sparkle" */ = { @@ -12911,6 +12918,10 @@ isa = XCSwiftPackageProductDependency; productName = NetworkProtectionUI; }; + 4B41EDAA2B1544B2001EEDF4 /* LoginItems */ = { + isa = XCSwiftPackageProductDependency; + productName = LoginItems; + }; 4B4BEC492A11B627001D9AC5 /* NetworkProtection */ = { isa = XCSwiftPackageProductDependency; productName = NetworkProtection; diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index df57efa2d0..8bccef09f9 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -14,8 +14,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/duckduckgo/BrowserServicesKit", "state" : { - "revision" : "543e1d7ed9b5743d4e6b0ebe18a5fbf8f1441f02", - "version" : "85.1.1" + "branch" : "diego/vpn-settings", + "revision" : "17b017754749363ce95ec4ea623cbdfdf8b75ad7" } }, { diff --git a/DuckDuckGo/DBP/LoginItem+DataBrokerProtection.swift b/DuckDuckGo/DBP/LoginItem+DataBrokerProtection.swift index 3f16d2c144..339b6d1d02 100644 --- a/DuckDuckGo/DBP/LoginItem+DataBrokerProtection.swift +++ b/DuckDuckGo/DBP/LoginItem+DataBrokerProtection.swift @@ -22,7 +22,7 @@ import LoginItems extension LoginItem { - static let dbpBackgroundAgent = LoginItem(bundleId: Bundle.main.dbpBackgroundAgentBundleId, log: .dbp) + static let dbpBackgroundAgent = LoginItem(bundleId: Bundle.main.dbpBackgroundAgentBundleId, defaults: .shared, log: .dbp) } diff --git a/DuckDuckGo/NavigationBar/View/NavigationBarViewController.swift b/DuckDuckGo/NavigationBar/View/NavigationBarViewController.swift index 9b581cae94..a1c6291045 100644 --- a/DuckDuckGo/NavigationBar/View/NavigationBarViewController.swift +++ b/DuckDuckGo/NavigationBar/View/NavigationBarViewController.swift @@ -419,10 +419,12 @@ final class NavigationBarViewController: NSViewController { name: AutoconsentUserScript.Constants.newSitePopupHidden, object: nil) +#if NETWORK_PROTECTION NotificationCenter.default.addObserver(self, selector: #selector(showVPNUninstalledFeedback(_:)), name: NetworkProtectionFeatureDisabler.vpnUninstalledNotificationName, object: nil) +#endif } @objc private func showVPNUninstalledFeedback(_ sender: Notification) { diff --git a/DuckDuckGo/Preferences/Model/PreferencesSection.swift b/DuckDuckGo/Preferences/Model/PreferencesSection.swift index e5ac478c96..5002b5666a 100644 --- a/DuckDuckGo/Preferences/Model/PreferencesSection.swift +++ b/DuckDuckGo/Preferences/Model/PreferencesSection.swift @@ -45,9 +45,11 @@ struct PreferencesSection: Hashable, Identifiable { panes.append(.duckPlayer) } +#if NETWORK_PROTECTION if includingVPN { panes.append(.vpn) } +#endif return panes }() @@ -69,7 +71,9 @@ enum PreferencePaneIdentifier: String, Equatable, Hashable, Identifiable { case sync case appearance case privacy +#if NETWORK_PROTECTION case vpn +#endif #if SUBSCRIPTION case subscription #endif @@ -103,8 +107,10 @@ enum PreferencePaneIdentifier: String, Equatable, Hashable, Identifiable { return UserText.appearance case .privacy: return UserText.privacy +#if NETWORK_PROTECTION case .vpn: return UserText.vpn +#endif #if SUBSCRIPTION case .subscription: return UserText.subscription @@ -130,8 +136,10 @@ enum PreferencePaneIdentifier: String, Equatable, Hashable, Identifiable { return "Appearance" case .privacy: return "Privacy" +#if NETWORK_PROTECTION case .vpn: return "VPN" +#endif #if SUBSCRIPTION case .subscription: return "Privacy" diff --git a/DuckDuckGo/Preferences/Model/PreferencesSidebarModel.swift b/DuckDuckGo/Preferences/Model/PreferencesSidebarModel.swift index c20f61e4bd..363378641a 100644 --- a/DuckDuckGo/Preferences/Model/PreferencesSidebarModel.swift +++ b/DuckDuckGo/Preferences/Model/PreferencesSidebarModel.swift @@ -53,7 +53,9 @@ final class PreferencesSidebarModel: ObservableObject { } .store(in: &cancellables) +#if NETWORK_PROTECTION setupVPNPaneVisibility() +#endif } @MainActor @@ -63,7 +65,11 @@ final class PreferencesSidebarModel: ObservableObject { includeDuckPlayer: Bool ) { let loadSections = { +#if NETWORK_PROTECTION let includingVPN = DefaultNetworkProtectionVisibility().isOnboarded +#else + let includingVPN = false +#endif return PreferencesSection.defaultSections(includingDuckPlayer: includeDuckPlayer, includingVPN: includingVPN) } @@ -75,6 +81,7 @@ final class PreferencesSidebarModel: ObservableObject { // MARK: - Setup +#if NETWORK_PROTECTION private func setupVPNPaneVisibility() { DefaultNetworkProtectionVisibility().onboardStatusPublisher .receive(on: DispatchQueue.main) @@ -89,6 +96,7 @@ final class PreferencesSidebarModel: ObservableObject { } .store(in: &cancellables) } +#endif // MARK: - Refreshing logic diff --git a/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift b/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift index 24ceabbecb..95b5ed97a7 100644 --- a/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift +++ b/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift @@ -16,6 +16,8 @@ // limitations under the License. // +#if NETWORK_PROTECTION + import AppKit import Combine import Foundation @@ -112,3 +114,5 @@ final class VPNPreferencesModel: ObservableObject { return alert } } + +#endif diff --git a/DuckDuckGo/Preferences/View/PreferencesRootView.swift b/DuckDuckGo/Preferences/View/PreferencesRootView.swift index ab0f8ab51f..63a9f8b1e9 100644 --- a/DuckDuckGo/Preferences/View/PreferencesRootView.swift +++ b/DuckDuckGo/Preferences/View/PreferencesRootView.swift @@ -59,8 +59,12 @@ extension Preferences { AppearanceView(model: .shared) case .privacy: PrivacyView(model: PrivacyPreferencesModel()) + +#if NETWORK_PROTECTION case .vpn: VPNView(model: VPNPreferencesModel()) +#endif + #if SUBSCRIPTION case .subscription: makeSubscriptionView() diff --git a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift index cb16728d5c..b30d3b8358 100644 --- a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift +++ b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift @@ -16,6 +16,8 @@ // limitations under the License. // +#if NETWORK_PROTECTION + import SwiftUI import SwiftUIExtensions @@ -101,3 +103,5 @@ extension Preferences { } } } + +#endif diff --git a/DuckDuckGo/Preferences/View/PreferencesViewController.swift b/DuckDuckGo/Preferences/View/PreferencesViewController.swift index 6af604a501..0289ac6afc 100644 --- a/DuckDuckGo/Preferences/View/PreferencesViewController.swift +++ b/DuckDuckGo/Preferences/View/PreferencesViewController.swift @@ -19,7 +19,10 @@ import AppKit import SwiftUI import Combine + +#if NETWORK_PROTECTION import NetworkProtection +#endif final class PreferencesViewController: NSViewController { From bd8e2d0fccfefa1ea8ea5703eafa18bfbeb06bc6 Mon Sep 17 00:00:00 2001 From: Sam Symons Date: Mon, 27 Nov 2023 14:51:54 -0800 Subject: [PATCH 36/40] Fix test compilation. --- .../NetworkProtectionStatusBarMenuTests.swift | 4 ++-- UnitTests/Preferences/PreferencesSidebarModelTests.swift | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/LocalPackages/NetworkProtectionMac/Tests/NetworkProtectionUITests/NetworkProtectionStatusBarMenuTests.swift b/LocalPackages/NetworkProtectionMac/Tests/NetworkProtectionUITests/NetworkProtectionStatusBarMenuTests.swift index 39236a194e..56842e070e 100644 --- a/LocalPackages/NetworkProtectionMac/Tests/NetworkProtectionUITests/NetworkProtectionStatusBarMenuTests.swift +++ b/LocalPackages/NetworkProtectionMac/Tests/NetworkProtectionUITests/NetworkProtectionStatusBarMenuTests.swift @@ -49,7 +49,7 @@ final class StatusBarMenuTests: XCTestCase { statusReporter: MockNetworkProtectionStatusReporter(), controller: TestTunnelController(), iconProvider: MenuIconProvider(), - menuItems: []) + menuItems: { [] }) menu.show() @@ -65,7 +65,7 @@ final class StatusBarMenuTests: XCTestCase { statusReporter: MockNetworkProtectionStatusReporter(), controller: TestTunnelController(), iconProvider: MenuIconProvider(), - menuItems: []) + menuItems: { [] }) menu.hide() diff --git a/UnitTests/Preferences/PreferencesSidebarModelTests.swift b/UnitTests/Preferences/PreferencesSidebarModelTests.swift index 61e59bf439..f601cb90f4 100644 --- a/UnitTests/Preferences/PreferencesSidebarModelTests.swift +++ b/UnitTests/Preferences/PreferencesSidebarModelTests.swift @@ -31,7 +31,7 @@ final class PreferencesSidebarModelTests: XCTestCase { } private func PreferencesSidebarModel(loadSections: [PreferencesSection]? = nil, tabSwitcherTabs: [Tab.TabContent] = Tab.TabContent.displayableTabTypes) -> DuckDuckGo_Privacy_Browser.PreferencesSidebarModel { - return DuckDuckGo_Privacy_Browser.PreferencesSidebarModel(loadSections: { loadSections ?? PreferencesSection.defaultSections(includingDuckPlayer: false) }, tabSwitcherTabs: tabSwitcherTabs, privacyConfigurationManager: MockPrivacyConfigurationManager()) + return DuckDuckGo_Privacy_Browser.PreferencesSidebarModel(loadSections: { loadSections ?? PreferencesSection.defaultSections(includingDuckPlayer: false, includingVPN: false) }, tabSwitcherTabs: tabSwitcherTabs, privacyConfigurationManager: MockPrivacyConfigurationManager()) } func testWhenInitializedThenFirstPaneInFirstSectionIsSelected() throws { From 4300489ab934316f0af542e0a87eba39a1d84dce Mon Sep 17 00:00:00 2001 From: Sam Symons Date: Mon, 27 Nov 2023 14:58:09 -0800 Subject: [PATCH 37/40] Fix SwiftLint violations. --- DuckDuckGo/Preferences/View/PreferencesRootView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DuckDuckGo/Preferences/View/PreferencesRootView.swift b/DuckDuckGo/Preferences/View/PreferencesRootView.swift index 63a9f8b1e9..e618c9cb51 100644 --- a/DuckDuckGo/Preferences/View/PreferencesRootView.swift +++ b/DuckDuckGo/Preferences/View/PreferencesRootView.swift @@ -64,7 +64,7 @@ extension Preferences { case .vpn: VPNView(model: VPNPreferencesModel()) #endif - + #if SUBSCRIPTION case .subscription: makeSubscriptionView() From 4849b7b6f0c2181dbd3a80e0a1b91e1867a4191b Mon Sep 17 00:00:00 2001 From: Sam Symons Date: Mon, 27 Nov 2023 15:02:43 -0800 Subject: [PATCH 38/40] =?UTF-8?q?Fix=20whitespace=E2=80=A6=20again=3F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DuckDuckGo/Preferences/View/PreferencesRootView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DuckDuckGo/Preferences/View/PreferencesRootView.swift b/DuckDuckGo/Preferences/View/PreferencesRootView.swift index e618c9cb51..8b0c2fdbd4 100644 --- a/DuckDuckGo/Preferences/View/PreferencesRootView.swift +++ b/DuckDuckGo/Preferences/View/PreferencesRootView.swift @@ -64,7 +64,7 @@ extension Preferences { case .vpn: VPNView(model: VPNPreferencesModel()) #endif - + #if SUBSCRIPTION case .subscription: makeSubscriptionView() From 0bc21e1031aa6e33955077d745683915f832e0e0 Mon Sep 17 00:00:00 2001 From: Sam Symons Date: Mon, 27 Nov 2023 17:44:20 -0800 Subject: [PATCH 39/40] Fix post-merge issues. --- .../DBP/LoginItem+DataBrokerProtection.swift | 2 +- .../LoginItem+NetworkProtection.swift | 4 ++-- .../NetworkProtectionAppEvents.swift | 2 +- .../NetworkProtectionDebugMenu.swift | 14 ++------------ .../NetworkProtectionDebugUtilities.swift | 2 +- .../NetworkProtectionNavBarPopoverManager.swift | 4 ++-- .../Preferences/Model/VPNPreferencesModel.swift | 4 ++-- .../NetworkProtectionFeatureVisibility.swift | 2 +- DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift | 2 +- DuckDuckGoVPN/TunnelControllerIPCService.swift | 4 ++-- 10 files changed, 15 insertions(+), 25 deletions(-) diff --git a/DuckDuckGo/DBP/LoginItem+DataBrokerProtection.swift b/DuckDuckGo/DBP/LoginItem+DataBrokerProtection.swift index 339b6d1d02..50413b3acf 100644 --- a/DuckDuckGo/DBP/LoginItem+DataBrokerProtection.swift +++ b/DuckDuckGo/DBP/LoginItem+DataBrokerProtection.swift @@ -22,7 +22,7 @@ import LoginItems extension LoginItem { - static let dbpBackgroundAgent = LoginItem(bundleId: Bundle.main.dbpBackgroundAgentBundleId, defaults: .shared, log: .dbp) + static let dbpBackgroundAgent = LoginItem(bundleId: Bundle.main.dbpBackgroundAgentBundleId, defaults: .dbp, log: .dbp) } diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/LoginItem+NetworkProtection.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/LoginItem+NetworkProtection.swift index 74e4c40467..38caf2dc7c 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/LoginItem+NetworkProtection.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/LoginItem+NetworkProtection.swift @@ -21,9 +21,9 @@ import LoginItems extension LoginItem { - static let vpnMenu = LoginItem(bundleId: Bundle.main.vpnMenuAgentBundleId, defaults: .shared, log: .networkProtection) + static let vpnMenu = LoginItem(bundleId: Bundle.main.vpnMenuAgentBundleId, defaults: .netP, log: .networkProtection) #if NETP_SYSTEM_EXTENSION - static let notificationsAgent = LoginItem(bundleId: Bundle.main.notificationsAgentBundleId, defaults: .shared, log: .networkProtection) + static let notificationsAgent = LoginItem(bundleId: Bundle.main.notificationsAgentBundleId, defaults: .netP, log: .networkProtection) #endif } diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionAppEvents.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionAppEvents.swift index c1b5573093..fc494b066e 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionAppEvents.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionAppEvents.swift @@ -169,7 +169,7 @@ final class NetworkProtectionAppEvents { // MARK: - Legacy Login Item and Extension private func removeLegacyLoginItemAndVPNConfiguration() async { - LoginItem(bundleId: legacyAgentBundleID, defaults: .shared).forceStop() + LoginItem(bundleId: legacyAgentBundleID, defaults: .netP).forceStop() let tunnels = try? await NETunnelProviderManager.loadAllFromPreferences() let tunnel = tunnels?.first { diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift index 57d937c776..cc6b0871ed 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift @@ -190,12 +190,7 @@ final class NetworkProtectionDebugMenu: NSMenu { @objc func resetAllState(_ sender: Any?) { Task { @MainActor in guard case .alertFirstButtonReturn = await NSAlert.resetNetworkProtectionAlert().runModal() else { return } - - do { - try await debugUtilities.resetAllState(keepAuthToken: false) - } catch { - await NSAlert(error: error).runModal() - } + await debugUtilities.resetAllState(keepAuthToken: false) } } @@ -204,12 +199,7 @@ final class NetworkProtectionDebugMenu: NSMenu { @objc func resetAllKeepingInvite(_ sender: Any?) { Task { @MainActor in guard case .alertFirstButtonReturn = await NSAlert.resetNetworkProtectionAlert().runModal() else { return } - - do { - try await debugUtilities.resetAllState(keepAuthToken: true) - } catch { - await NSAlert(error: error).runModal() - } + await debugUtilities.resetAllState(keepAuthToken: true) } } diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift index df07768a36..c723da5658 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift @@ -44,7 +44,7 @@ final class NetworkProtectionDebugUtilities { // MARK: - Initializers - init(loginItemsManager: LoginItemsManager = .init(), settings: VPNSettings = .init(defaults: .shared)) { + init(loginItemsManager: LoginItemsManager = .init(), settings: VPNSettings = .init(defaults: .netP)) { self.loginItemsManager = loginItemsManager self.settings = settings diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift index 0f0464e120..64b5642fe3 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift @@ -59,10 +59,10 @@ final class NetworkProtectionNavBarPopoverManager { ) let onboardingStatusPublisher = UserDefaults.netP.networkProtectionOnboardingStatusPublisher - let settings = VPNSettings(defaults: .netP) + _ = VPNSettings(defaults: .netP) let popover = NetworkProtectionPopover(controller: controller, onboardingStatusPublisher: onboardingStatusPublisher, statusReporter: statusReporter) { - var menuItems = [ + let menuItems = [ NetworkProtectionStatusView.Model.MenuItem( name: UserText.networkProtectionNavBarStatusMenuVPNSettings, action: { let appLauncher = AppLauncher(appBundleURL: Bundle.main.bundleURL) diff --git a/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift b/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift index 95b5ed97a7..453a505449 100644 --- a/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift +++ b/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift @@ -65,8 +65,8 @@ final class VPNPreferencesModel: ObservableObject { private let settings: VPNSettings private var cancellables = Set() - init(settings: VPNSettings = .init(defaults: .shared), - defaults: UserDefaults = .shared) { + init(settings: VPNSettings = .init(defaults: .netP), + defaults: UserDefaults = .netP) { self.settings = settings connectOnLogin = settings.connectOnLogin diff --git a/DuckDuckGo/Waitlist/NetworkProtectionFeatureVisibility.swift b/DuckDuckGo/Waitlist/NetworkProtectionFeatureVisibility.swift index 50dafce2e3..370acfc068 100644 --- a/DuckDuckGo/Waitlist/NetworkProtectionFeatureVisibility.swift +++ b/DuckDuckGo/Waitlist/NetworkProtectionFeatureVisibility.swift @@ -47,7 +47,7 @@ struct DefaultNetworkProtectionVisibility: NetworkProtectionFeatureVisibility { networkProtectionFeatureActivation: NetworkProtectionFeatureActivation = NetworkProtectionKeychainTokenStore(), featureOverrides: WaitlistBetaOverriding = DefaultWaitlistBetaOverrides(), featureDisabler: NetworkProtectionFeatureDisabling = NetworkProtectionFeatureDisabler(), - defaults: UserDefaults = .shared, + defaults: UserDefaults = .netP, log: OSLog = .networkProtection) { self.privacyConfigurationManager = privacyConfigurationManager diff --git a/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift b/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift index 07c8d4defc..4fb762d46c 100644 --- a/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift +++ b/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift @@ -176,7 +176,7 @@ final class DuckDuckGoVPNAppDelegate: NSObject, NSApplicationDelegate { } } - let launchInformation = LoginItemLaunchInformation(agentBundleID: Bundle.main.bundleIdentifier!, defaults: .shared) + let launchInformation = LoginItemLaunchInformation(agentBundleID: Bundle.main.bundleIdentifier!, defaults: .netP) let launchedOnStartup = launchInformation.wasLaunchedByStartup launchInformation.update() diff --git a/DuckDuckGoVPN/TunnelControllerIPCService.swift b/DuckDuckGoVPN/TunnelControllerIPCService.swift index febee3cff8..79687fd9e2 100644 --- a/DuckDuckGoVPN/TunnelControllerIPCService.swift +++ b/DuckDuckGoVPN/TunnelControllerIPCService.swift @@ -39,7 +39,7 @@ final class TunnelControllerIPCService { init(tunnelController: TunnelController, networkExtensionController: NetworkExtensionController, statusReporter: NetworkProtectionStatusReporter, - defaults: UserDefaults = .shared) { + defaults: UserDefaults = .netP) { self.tunnelController = tunnelController self.networkExtensionController = networkExtensionController @@ -112,7 +112,7 @@ extension TunnelControllerIPCService: IPCServerInterface { } func debugCommand(_ command: DebugCommand) async throws { - let activeSession = try await ConnectionSessionUtilities.activeSession(networkExtensionBundleID: Bundle.main.networkExtensionBundleID) + _ = try await ConnectionSessionUtilities.activeSession(networkExtensionBundleID: Bundle.main.networkExtensionBundleID) switch command { case .removeSystemExtension: From c37d3d86750f42cd99c5abc833d3a039928626b5 Mon Sep 17 00:00:00 2001 From: Sam Symons Date: Mon, 27 Nov 2023 18:05:43 -0800 Subject: [PATCH 40/40] Set BSK to 86.0.0. --- DuckDuckGo.xcodeproj/project.pbxproj | 4 ++-- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- LocalPackages/Account/Package.swift | 2 +- LocalPackages/DataBrokerProtection/Package.swift | 2 +- LocalPackages/NetworkProtectionMac/Package.swift | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 77cf372873..d5b9ce06ae 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -12732,8 +12732,8 @@ isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit"; requirement = { - branch = "diego/vpn-settings"; - kind = branch; + kind = exactVersion; + version = 86.0.0; }; }; AA06B6B52672AF8100F541C5 /* XCRemoteSwiftPackageReference "Sparkle" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 8bccef09f9..b413c9f26b 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -14,8 +14,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/duckduckgo/BrowserServicesKit", "state" : { - "branch" : "diego/vpn-settings", - "revision" : "17b017754749363ce95ec4ea623cbdfdf8b75ad7" + "revision" : "1331652ad0dc21c23b495b4a9a42e2a0eb44859d", + "version" : "86.0.0" } }, { diff --git a/LocalPackages/Account/Package.swift b/LocalPackages/Account/Package.swift index c93ca48150..1f44709b52 100644 --- a/LocalPackages/Account/Package.swift +++ b/LocalPackages/Account/Package.swift @@ -12,7 +12,7 @@ let package = Package( targets: ["Account"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "85.1.1"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "86.0.0"), .package(path: "../Purchase") ], targets: [ diff --git a/LocalPackages/DataBrokerProtection/Package.swift b/LocalPackages/DataBrokerProtection/Package.swift index ee121cf018..e27f0fb5fd 100644 --- a/LocalPackages/DataBrokerProtection/Package.swift +++ b/LocalPackages/DataBrokerProtection/Package.swift @@ -29,7 +29,7 @@ let package = Package( targets: ["DataBrokerProtection"]) ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "85.1.1"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "86.0.0"), .package(path: "../PixelKit"), .package(path: "../SwiftUIExtensions"), .package(path: "../XPCHelper") diff --git a/LocalPackages/NetworkProtectionMac/Package.swift b/LocalPackages/NetworkProtectionMac/Package.swift index a9655152d1..ea40c43fe6 100644 --- a/LocalPackages/NetworkProtectionMac/Package.swift +++ b/LocalPackages/NetworkProtectionMac/Package.swift @@ -30,7 +30,7 @@ let package = Package( .library(name: "NetworkProtectionUI", targets: ["NetworkProtectionUI"]) ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "85.1.1"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "86.0.0"), .package(path: "../XPCHelper"), .package(path: "../SwiftUIExtensions") ],