Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VPN Domain exclusions (internal release) #3045

Merged
merged 56 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
bcd7e47
WIP
diegoreymendez Jul 16, 2024
9494bb4
Merge branch 'main' into diego/exclude-domains
diegoreymendez Jul 16, 2024
de8cdd6
WIP
diegoreymendez Jul 16, 2024
65016ab
WIP
diegoreymendez Jul 17, 2024
1e16f9d
Merges the latest from main
diegoreymendez Jul 22, 2024
d2d4107
WIP
diegoreymendez Jul 23, 2024
db0301b
Adds support for domain exclusions in VPN
diegoreymendez Jul 25, 2024
065e52d
Disables VPN restart on launch to test exclusions
diegoreymendez Jul 25, 2024
89ea86b
WIP
diegoreymendez Jul 26, 2024
8629bf4
Merges the latest from main
diegoreymendez Jul 26, 2024
af7808c
Fixes the button size and text in the add-domain dialog
diegoreymendez Jul 26, 2024
dcdcd61
WIP
diegoreymendez Jul 28, 2024
1e4050c
Merge branch 'main' into diego/exclude-domains
diegoreymendez Jul 28, 2024
ac4a7a8
WIP
diegoreymendez Jul 29, 2024
5e4bd3a
Fixes a warning in the code
diegoreymendez Jul 30, 2024
2c3c94a
Drops the www prefix from VPN troubleshooting UI
diegoreymendez Jul 30, 2024
3f8d157
Some UI improvements to the domain exclusions UI
diegoreymendez Jul 30, 2024
5fb6862
Addresses design feedback
diegoreymendez Jul 30, 2024
1796a25
Cleans up dead code
diegoreymendez Jul 30, 2024
bf67171
Improves site troubleshooting UI
diegoreymendez Jul 30, 2024
f589014
Improvements to site troubleshooting
diegoreymendez Jul 30, 2024
05b0d90
Merges the latest from main
diegoreymendez Jul 30, 2024
70e825b
Updates BSK
diegoreymendez Jul 30, 2024
114a9f9
Refactored some of the status view code
diegoreymendez Jul 31, 2024
362e1eb
Updates BSK
diegoreymendez Jul 31, 2024
fe04a2c
Updates BSK
diegoreymendez Jul 31, 2024
2e3dee5
Rolls back some unnecessary changes
diegoreymendez Aug 1, 2024
a7bcacc
WIP
diegoreymendez Aug 1, 2024
2eba344
Rolls back an unintentional change
diegoreymendez Aug 1, 2024
13e2e80
WIP
diegoreymendez Aug 1, 2024
d4345a4
VPN code cleanup
diegoreymendez Aug 1, 2024
b83bc3e
Merges the latest from main
diegoreymendez Aug 1, 2024
cac146a
WIP
diegoreymendez Aug 1, 2024
a093b0d
Removes some dead code
diegoreymendez Aug 1, 2024
b0c69c7
Fixes a build issue
diegoreymendez Aug 1, 2024
111df3f
Merge branch 'diego/vpn-waitlist-and-debug-menu-cleanup' into diego/e…
diegoreymendez Aug 1, 2024
563ca59
Removes some whitespace
diegoreymendez Aug 1, 2024
4f7f143
WIP
diegoreymendez Aug 1, 2024
56c5cd5
Adds an active domain publisher
diegoreymendez Aug 2, 2024
aa6d8f1
Removing some test code
diegoreymendez Aug 2, 2024
5324fc3
Merges the latest from main, updates BSK
diegoreymendez Aug 2, 2024
03f3b07
Fixes some Swiftlint warnings
diegoreymendez Aug 2, 2024
9bfcd22
Fixes an error message
diegoreymendez Aug 5, 2024
316d26e
Fills in a TBD
diegoreymendez Aug 5, 2024
7e8947f
Merges the latest from main
diegoreymendez Aug 5, 2024
a5f6d55
Updates BSK
diegoreymendez Aug 5, 2024
1762b57
Fixes unit tests
diegoreymendez Aug 5, 2024
40f64ad
Fixes a compilation error
diegoreymendez Aug 5, 2024
61e1572
Fixes some compilation errors
diegoreymendez Aug 5, 2024
aed9c62
Fixes some code warnings
diegoreymendez Aug 5, 2024
db9048e
Fixes some conditional compilation errors
diegoreymendez Aug 5, 2024
efaa013
Fixes a unit test
diegoreymendez Aug 5, 2024
4d71849
Disabling a flaky test
diegoreymendez Aug 5, 2024
649eadb
Updates to BSK 180.0.1
diegoreymendez Aug 5, 2024
e972748
Disables testWhenPDFMainMenuPrintChosen_printDialogOpens
diegoreymendez Aug 5, 2024
1776333
Disables a flaky test
diegoreymendez Aug 5, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 70 additions & 2 deletions DuckDuckGo.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/duckduckgo/BrowserServicesKit",
"state" : {
"revision" : "ece50dc4a946de4d1d82c50a75a7dac101a7fb70",
"version" : "177.0.2"
"revision" : "23a41520dbbf6007d00bdb31a63984f0f8382216"
}
},
{
Expand Down
39 changes: 6 additions & 33 deletions DuckDuckGo/Application/URLEventHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ import DataBrokerProtection
// @MainActor
final class URLEventHandler {

@MainActor
private static let vpnURLEventHandler = VPNURLEventHandler()
diegoreymendez marked this conversation as resolved.
Show resolved Hide resolved

private let handler: (URL) -> Void

private var didFinishLaunching = false
Expand Down Expand Up @@ -109,7 +112,9 @@ final class URLEventHandler {

private static func openURL(_ url: URL) {
if url.scheme?.isNetworkProtectionScheme == true {
handleNetworkProtectionURL(url)
Task { @MainActor in
await vpnURLEventHandler.handle(url)
}
}

#if DBP
Expand Down Expand Up @@ -141,38 +146,6 @@ final class URLEventHandler {
}
}

/// Handles NetP URLs
private static func handleNetworkProtectionURL(_ url: URL) {
DispatchQueue.main.async {
switch url {
case VPNAppLaunchCommand.showStatus.launchURL:
Task {
await WindowControllersManager.shared.showNetworkProtectionStatus()
}
case VPNAppLaunchCommand.showSettings.launchURL:
WindowControllersManager.shared.showPreferencesTab(withSelectedPane: .vpn)
case VPNAppLaunchCommand.shareFeedback.launchURL:
WindowControllersManager.shared.showShareFeedbackModal()
case VPNAppLaunchCommand.justOpen.launchURL:
WindowControllersManager.shared.showMainWindow()
case VPNAppLaunchCommand.showVPNLocations.launchURL:
WindowControllersManager.shared.showPreferencesTab(withSelectedPane: .vpn)
WindowControllersManager.shared.showLocationPickerSheet()
case VPNAppLaunchCommand.showPrivacyPro.launchURL:
let url = Application.appDelegate.subscriptionManager.url(for: .purchase)
WindowControllersManager.shared.showTab(with: .subscription(url))
PixelKit.fire(PrivacyProPixel.privacyProOfferScreenImpression)
#if !APPSTORE && !DEBUG
case VPNAppLaunchCommand.moveAppToApplications.launchURL:
// this should be run after NSApplication.shared is set
PFMoveToApplicationsFolderIfNecessary(false)
#endif
default:
return
}
}
}

#if DBP
/// Handles DBP URLs
///
Expand Down
12 changes: 12 additions & 0 deletions DuckDuckGo/Common/Localizables/UserText+NetworkProtection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ extension UserText {
// MARK: - Setting Titles
// "vpn.location.title" - Location section title in VPN settings
static let vpnLocationTitle = "Location"
// "vpn.excluded.sites.title" - Excluded Sites title in VPN settings
static let vpnExcludedSitesTitle = "Excluded Sites"
// "vpn.general.title" - General section title in VPN settings
static let vpnGeneralTitle = "General"
// "vpn.shortcuts.settings.title" - Shortcuts section title in VPN settings
Expand Down Expand Up @@ -161,6 +163,16 @@ extension UserText {
return String(format: message, count)
}

// MARK: - Excluded Domains
// "vpn.setting.excluded.domains.description" - Excluded Sites description
static let vpnExcludedDomainsDescription = "Websites you selected to be excluded even when the VPN is connected."
// "vpn.setting.excluded.domains.manage.button.title" - Excluded Sites management button title
static let vpnExcludedDomainsManageButtonTitle = "Manage Excluded Sites…"
// "vpn.excluded.domains.add.domain" - Add Domain button for the excluded sites view
static let vpnExcludedDomainsAddDomain = "Add Website"
// "vpn.excluded.domains.title" - Title for the excluded sites view
static let vpnExcludedDomainsTitle = "Excluded Websites"

// MARK: - DNS
// "vpn.dns.server.title" - Title of the DNS Server section
static let vpnDnsServerTitle = "DNS Server"
Expand Down
3 changes: 3 additions & 0 deletions DuckDuckGo/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -57085,6 +57085,9 @@
}
}
}
},
"URL" : {

},
"version" : {
"comment" : "Displays the version and build numbers",
Expand Down
20 changes: 14 additions & 6 deletions DuckDuckGo/NavigationBar/View/NavigationBarPopovers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ protocol PopoverPresenter {
func show(_ popover: NSPopover, positionedBelow view: NSView)
}

@MainActor
protocol NetPPopoverManager: AnyObject {
var isShown: Bool { get }

Expand Down Expand Up @@ -133,8 +134,10 @@ final class NavigationBarPopovers: NSObject, PopoverPresenter {
}

func toggleNetworkProtectionPopover(from button: MouseOverButton, withDelegate delegate: NSPopoverDelegate) {
if let popover = networkProtectionPopoverManager.toggle(positionedBelow: button, withDelegate: delegate) {
bindIsMouseDownState(of: button, to: popover)
Task { @MainActor in
if let popover = networkProtectionPopoverManager.toggle(positionedBelow: button, withDelegate: delegate) {
bindIsMouseDownState(of: button, to: popover)
}
}
}

Expand Down Expand Up @@ -199,8 +202,10 @@ final class NavigationBarPopovers: NSObject, PopoverPresenter {
downloadsPopover?.close()
}

if networkProtectionPopoverManager.isShown {
networkProtectionPopoverManager.close()
Task { @MainActor in
if networkProtectionPopoverManager.isShown {
networkProtectionPopoverManager.close()
}
}

if bookmarkPopover?.isShown ?? false {
Expand Down Expand Up @@ -432,8 +437,11 @@ final class NavigationBarPopovers: NSObject, PopoverPresenter {
// MARK: - VPN

func showNetworkProtectionPopover(positionedBelow button: MouseOverButton, withDelegate delegate: NSPopoverDelegate) {
let popover = networkProtectionPopoverManager.show(positionedBelow: button, withDelegate: delegate)
bindIsMouseDownState(of: button, to: popover)

Task { @MainActor in
let popover = networkProtectionPopoverManager.show(positionedBelow: button, withDelegate: delegate)
bindIsMouseDownState(of: button, to: popover)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
//
// ActiveDomainPublisher.swift
//
// Copyright © 2024 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 Combine
import Foundation

/// A convenience class for publishing the active domain
///
/// The active domain is the domain loaded in the last active tab within the last active window.
///
final class ActiveDomainPublisher {

private let windowControllersManager: WindowControllersManager
private var activeWindowControllerCancellable: AnyCancellable?
private var activeTabViewModelCancellable: AnyCancellable?
private var activeTabContentCancellable: AnyCancellable?

@MainActor
@Published
private var activeWindowController: MainWindowController? {
didSet {
subscribeToActiveTabViewModel()
}
}

@MainActor
@Published
private var activeTab: Tab? {
didSet {
subscribeToActiveTabContentChanges()
}
}

init(windowControllersManager: WindowControllersManager) {
self.windowControllersManager = windowControllersManager

Task { @MainActor in
subscribeToKeyWindowControllerChanges()
}
}

@Published
private(set) var activeDomain: String?

@MainActor
private func subscribeToKeyWindowControllerChanges() {
activeWindowControllerCancellable = windowControllersManager
.didChangeKeyWindowController
.prepend(windowControllersManager.lastKeyMainWindowController)
.assign(to: \.activeWindowController, onWeaklyHeld: self)
}

@MainActor
private func subscribeToActiveTabViewModel() {
activeTabViewModelCancellable = activeWindowController?.mainViewController.tabCollectionViewModel.$selectedTabViewModel
.map(\.?.tab)
.assign(to: \.activeTab, onWeaklyHeld: self)
}

@MainActor
private func subscribeToActiveTabContentChanges() {
activeTabContentCancellable = activeTab?.$content
.map(domain(from:))
.removeDuplicates()
.assign(to: \.activeDomain, onWeaklyHeld: self)
}

private func domain(from tabContent: Tab.TabContent) -> String? {
if case .url(let url, _, _) = tabContent {

return url.host
} else {
return nil
}
}
}

extension ActiveDomainPublisher: Publisher {
typealias Output = String?
typealias Failure = Never

func receive<S>(subscriber: S) where S: Subscriber, Never == S.Failure, String? == S.Input {
$activeDomain.subscribe(subscriber)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,14 @@ final class NetworkProtectionDebugMenu: NSMenu {

NSMenuItem.separator()

NSMenuItem(title: "Adapter") {
NSMenuItem(title: "Restart Adapter", action: #selector(NetworkProtectionDebugMenu.restartAdapter(_:)))
.targetting(self)

NSMenuItem(title: "Re-create Adapter", action: #selector(NetworkProtectionDebugMenu.restartAdapter(_:)))
.targetting(self)
}

NSMenuItem(title: "Tunnel Settings") {
shouldIncludeAllNetworksMenuItem
.targetting(self)
Expand Down Expand Up @@ -218,6 +226,18 @@ final class NetworkProtectionDebugMenu: NSMenu {
}
}

/// Removes the system extension and agents for DuckDuckGo VPN.
diegoreymendez marked this conversation as resolved.
Show resolved Hide resolved
///
@objc func restartAdapter(_ sender: Any?) {
Task { @MainActor in
do {
try await debugUtilities.restartAdapter()
} catch {
await NSAlert(error: error).runModal()
}
}
}

/// Sends a test user notification.
///
@objc func sendTestNotification(_ sender: Any?) {
Expand Down Expand Up @@ -449,8 +469,8 @@ final class NetworkProtectionDebugMenu: NSMenu {
private let ddgBrowserAppIdentifier = Bundle.main.bundleIdentifier!

private func updateExclusionsMenu() {
excludeDBPTrafficFromVPN.state = transparentProxySettings.isExcluding(dbpBackgroundAppIdentifier) ? .on : .off
excludeDDGBrowserTrafficFromVPN.state = transparentProxySettings.isExcluding(ddgBrowserAppIdentifier) ? .on : .off
excludeDBPTrafficFromVPN.state = transparentProxySettings.isExcluding(appIdentifier: dbpBackgroundAppIdentifier) ? .on : .off
excludeDDGBrowserTrafficFromVPN.state = transparentProxySettings.isExcluding(appIdentifier: ddgBrowserAppIdentifier) ? .on : .off
diegoreymendez marked this conversation as resolved.
Show resolved Hide resolved
}

@objc private func toggleExcludeDBPBackgroundAgent() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ final class NetworkProtectionDebugUtilities {

// MARK: - Debug commands for the extension

func restartAdapter() async throws {
try await ipcClient.command(.restartAdapter)
}

func resetAllState(keepAuthToken: Bool) async throws {
try await vpnUninstaller.uninstall(removeSystemExtension: true)

Expand Down
Loading
Loading