Skip to content

Commit

Permalink
Merge branch 'main' into fcappelli/oslog_to_logger
Browse files Browse the repository at this point in the history
# Conflicts:
#	DuckDuckGo.xcodeproj/project.pbxproj
#	DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
  • Loading branch information
federicocappelli committed Aug 19, 2024
2 parents 4f61d31 + 292fa4f commit b9326eb
Show file tree
Hide file tree
Showing 14 changed files with 541 additions and 28 deletions.
14 changes: 2 additions & 12 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -360,19 +360,9 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v3
with:
node-version: 16
cache: 'npm'
- name: Build bundle
run: |
npm ci
npm run rebuild-autoconsent
- name: Verify clean tree
- name: Skip
run: |
git update-index --refresh
git diff-index --quiet HEAD --
echo "Skipping autoconsent bundle verification during an experiment"
create-asana-task:
name: Create Asana Task
Expand Down
6 changes: 6 additions & 0 deletions DuckDuckGo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -2779,6 +2779,8 @@
F41D174125CB131900472416 /* NSColorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F41D174025CB131900472416 /* NSColorExtension.swift */; };
F44C130225C2DA0400426E3E /* NSAppearanceExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F44C130125C2DA0400426E3E /* NSAppearanceExtension.swift */; };
F4A6198C283CFFBB007F2080 /* ContentScopeFeatureFlagging.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4A6198B283CFFBB007F2080 /* ContentScopeFeatureFlagging.swift */; };
FD22255D2C64B68500199373 /* AutoconsentExperiment.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD22255C2C64B68500199373 /* AutoconsentExperiment.swift */; };
FD22255E2C64B68500199373 /* AutoconsentExperiment.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD22255C2C64B68500199373 /* AutoconsentExperiment.swift */; };
FD23FD2B28816606007F6985 /* AutoconsentMessageProtocolTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD23FD2A28816606007F6985 /* AutoconsentMessageProtocolTests.swift */; };
FD23FD2D2886A81D007F6985 /* AutoconsentManagement.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD23FD2C2886A81D007F6985 /* AutoconsentManagement.swift */; };
/* End PBXBuildFile section */
Expand Down Expand Up @@ -4315,6 +4317,7 @@
F41D174025CB131900472416 /* NSColorExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSColorExtension.swift; sourceTree = "<group>"; };
F44C130125C2DA0400426E3E /* NSAppearanceExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSAppearanceExtension.swift; sourceTree = "<group>"; };
F4A6198B283CFFBB007F2080 /* ContentScopeFeatureFlagging.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentScopeFeatureFlagging.swift; sourceTree = "<group>"; };
FD22255C2C64B68500199373 /* AutoconsentExperiment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoconsentExperiment.swift; sourceTree = "<group>"; };
FD23FD2A28816606007F6985 /* AutoconsentMessageProtocolTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AutoconsentMessageProtocolTests.swift; path = UnitTests/Autoconsent/AutoconsentMessageProtocolTests.swift; sourceTree = SOURCE_ROOT; };
FD23FD2C2886A81D007F6985 /* AutoconsentManagement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoconsentManagement.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
Expand Down Expand Up @@ -7950,6 +7953,7 @@
B31055BE27A1BA1D001AC618 /* userscript.js */,
FD23FD2C2886A81D007F6985 /* AutoconsentManagement.swift */,
B31055BC27A1BA1D001AC618 /* AutoconsentUserScript.swift */,
FD22255C2C64B68500199373 /* AutoconsentExperiment.swift */,
);
path = Autoconsent;
sourceTree = "<group>";
Expand Down Expand Up @@ -9997,6 +10001,7 @@
3706FAD3293F65D500E42796 /* DownloadsViewController.swift in Sources */,
3706FAD4293F65D500E42796 /* DataExtension.swift in Sources */,
3706FAD6293F65D500E42796 /* ConfigurationStore.swift in Sources */,
FD22255E2C64B68500199373 /* AutoconsentExperiment.swift in Sources */,
3706FAD7293F65D500E42796 /* Feedback.swift in Sources */,
1D0DE9422C3BB9CC0037ABC2 /* ReleaseNotesParser.swift in Sources */,
3707C722294B5D2900682A9F /* WKWebViewExtension.swift in Sources */,
Expand Down Expand Up @@ -12043,6 +12048,7 @@
B655124829A79465009BFE1C /* NavigationActionExtension.swift in Sources */,
9FA173EB2B7B232200EE4E6E /* AddEditBookmarkDialogView.swift in Sources */,
85308E25267FC9F2001ABD76 /* NSAlertExtension.swift in Sources */,
FD22255D2C64B68500199373 /* AutoconsentExperiment.swift in Sources */,
B69A14F62B4D701F00B9417D /* AddBookmarkPopoverViewModel.swift in Sources */,
4B59024826B3673600489384 /* ThirdPartyBrowser.swift in Sources */,
B60C6F7729B0E286007BFAA8 /* SearchNonexistentDomainNavigationResponder.swift in Sources */,
Expand Down
50 changes: 50 additions & 0 deletions DuckDuckGo/Autoconsent/AutoconsentExperiment.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//
// AutoconsentExperiment.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 Foundation
import Common

enum AutoconsentFilterlistExperiment: String, CaseIterable {
static var logic = AutoconsentExperimentLogic()
static var cohort: AutoconsentFilterlistExperiment? {
os_log("🚧 requesting CPM cohort", log: .autoconsent, type: .debug)
return logic.experimentCohort
}

case control = "fc"
case test = "ft"
}

final internal class AutoconsentExperimentLogic {
var experimentCohort: AutoconsentFilterlistExperiment? {
if let allocatedExperimentCohort,
// if the stored cohort doesn't match, allocate a new one
let cohort = AutoconsentFilterlistExperiment(rawValue: allocatedExperimentCohort)
{
os_log("🚧 existing CPM cohort: %s", log: .autoconsent, type: .debug, String(describing: cohort.rawValue))
return cohort
}
let cohort = AutoconsentFilterlistExperiment.allCases.randomElement()!
os_log("🚧 new CPM cohort: %s", log: .autoconsent, type: .debug, String(describing: cohort.rawValue))
allocatedExperimentCohort = cohort.rawValue
return cohort
}

@UserDefaultsWrapper(key: .autoconsentFilterlistExperimentCohort, defaultValue: nil)
var allocatedExperimentCohort: String?
}
5 changes: 4 additions & 1 deletion DuckDuckGo/Autoconsent/AutoconsentUserScript.swift
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@ extension AutoconsentUserScript {
}
let remoteConfig = self.config.settings(for: .autoconsent)
let disabledCMPs = remoteConfig["disabledCMPs"] as? [String] ?? []
let isFilterListExperimentEnabled = config.isSubfeatureEnabled(AutoconsentSubfeature.filterlistExperiment)
let enableFilterList = isFilterListExperimentEnabled && AutoconsentFilterlistExperiment.cohort == AutoconsentFilterlistExperiment.test

replyHandler([
"type": "initResp",
Expand All @@ -245,7 +247,8 @@ extension AutoconsentUserScript {
"enablePrehide": true,
"enableCosmeticRules": true,
"detectRetries": 20,
"isMainWorld": false
"isMainWorld": false,
"enableFilterList": enableFilterList
] as [String: Any?]
] as [String: Any?], nil)
}
Expand Down
446 changes: 445 additions & 1 deletion DuckDuckGo/Autoconsent/autoconsent-bundle.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions DuckDuckGo/Common/Utilities/UserDefaultsWrapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public struct UserDefaultsWrapper<T> {
case alwaysRequestDownloadLocationKey = "preferences.download-location.always-request"
case openDownloadsPopupOnCompletionKey = "preferences.downloads.open.on.completion"
case autoconsentEnabled = "preferences.autoconsent-enabled"
case autoconsentFilterlistExperimentCohort = "preferences.autoconsent.filterListExperimentCohort"
case duckPlayerMode = "preferences.duck-player"
case youtubeOverlayInteracted = "preferences.youtube-overlay-interacted"
case youtubeOverlayButtonsUsed = "preferences.youtube-overlay-user-used-buttons"
Expand Down
1 change: 1 addition & 0 deletions DuckDuckGo/Menus/MainMenu.swift
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,7 @@ final class MainMenu: NSMenu {
NSMenuItem(title: "Reset Email Protection InContext Signup Prompt", action: #selector(MainViewController.resetEmailProtectionInContextPrompt))
NSMenuItem(title: "Reset Pixels Storage", action: #selector(MainViewController.resetDailyPixels))
NSMenuItem(title: "Reset Remote Messages", action: #selector(AppDelegate.resetRemoteMessages))
NSMenuItem(title: "Reset CPM Experiment Cohort (needs restart)", action: #selector(AppDelegate.resetCpmCohort))
}.withAccessibilityIdentifier("MainMenu.resetData")
NSMenuItem(title: "UI Triggers") {
NSMenuItem(title: "Show Save Credentials Popover", action: #selector(MainViewController.showSaveCredentialsPopover))
Expand Down
4 changes: 4 additions & 0 deletions DuckDuckGo/Menus/MainMenuActions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,10 @@ extension AppDelegate {
@objc func resetRemoteMessages(_ sender: Any?) {
remoteMessagingClient.store?.resetRemoteMessages()
}

@objc func resetCpmCohort(_ sender: Any?) {
UserDefaultsWrapper.clear(.autoconsentFilterlistExperimentCohort)
}
}

extension MainViewController {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,14 @@ final class PrivacyDashboardViewController: NSViewController {

private let brokenSiteReporter: BrokenSiteReporter = {
BrokenSiteReporter(pixelHandler: { parameters in
let privacyConfigurationManager = ContentBlocking.shared.privacyConfigurationManager
var updatedParameters = parameters
// do not enroll users who have CPM disabled
if CookiePopupProtectionPreferences.shared.isAutoconsentEnabled && privacyConfigurationManager.privacyConfig.isSubfeatureEnabled(AutoconsentSubfeature.filterlistExperiment) {
updatedParameters["cpmExperiment"] = AutoconsentFilterlistExperiment.cohort == AutoconsentFilterlistExperiment.test ? "1" : "0"
}
PixelKit.fire(NonStandardEvent(NonStandardPixel.brokenSiteReport),
withAdditionalParameters: parameters,
withAdditionalParameters: updatedParameters,
allowedQueryReservedCharacters: BrokenSiteReport.allowedQueryReservedCharacters)
}, keyValueStoring: UserDefaults.standard)
}()
Expand Down
24 changes: 16 additions & 8 deletions DuckDuckGo/Tab/TabExtensions/AdClickAttributionTabExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ protocol AdClickLogicProtocol: AnyObject {

func applyInheritedAttribution(state: AdClickAttributionLogic.State?)
func onRulesChanged(latestRules: [ContentBlockerRulesManager.Rules])
func onRequestDetected(request: DetectedRequest)
func onRequestDetected(request: DetectedRequest, cpmExperimentOn: Bool?)

func onBackForwardNavigation(mainFrameURL: URL?)
func onProvisionalNavigation() async
Expand All @@ -79,12 +79,13 @@ extension ContentBlockerRulesUserScript: ContentBlockerScriptProtocol {}

final class AdClickAttributionTabExtension: TabExtension {

private static func makeAdClickAttributionDetection(with dependencies: any AdClickAttributionDependencies, delegate: AdClickAttributionLogic) -> AdClickAttributionDetection {
private static func makeAdClickAttributionDetection(with dependencies: any AdClickAttributionDependencies, delegate: AdClickAttributionLogic, cpmExperimentOn: Bool?) -> AdClickAttributionDetection {
let detection = AdClickAttributionDetection(feature: dependencies.adClickAttribution,
tld: dependencies.tld,
eventReporting: dependencies.attributionEvents,
errorReporting: dependencies.attributionDebugEvents,
log: OSLog.attribution)
log: OSLog.attribution,
cpmExperimentOn: cpmExperimentOn)
detection.delegate = delegate
return detection

Expand All @@ -99,9 +100,9 @@ final class AdClickAttributionTabExtension: TabExtension {
log: OSLog.attribution)
}

private static func makeAdClickAttribution(with dependencies: any AdClickAttributionDependencies) -> (AdClickLogicProtocol, AdClickAttributionDetecting) {
private static func makeAdClickAttribution(with dependencies: any AdClickAttributionDependencies, cpmExperimentOn: Bool?) -> (AdClickLogicProtocol, AdClickAttributionDetecting) {
let logic = makeAdClickAttributionLogic(with: dependencies)
let detection = makeAdClickAttributionDetection(with: dependencies, delegate: logic)
let detection = makeAdClickAttributionDetection(with: dependencies, delegate: logic, cpmExperimentOn: cpmExperimentOn)
return (logic, detection)
}

Expand All @@ -121,19 +122,26 @@ final class AdClickAttributionTabExtension: TabExtension {
}

private var cancellables = Set<AnyCancellable>()
private let cpmExperimentOn: Bool?

init(inheritedAttribution: AdClickAttributionLogic.State?,
userContentControllerFuture: some Publisher<some UserContentControllerProtocol, Never>,
contentBlockerRulesScriptPublisher: some Publisher<(any ContentBlockerScriptProtocol)?, Never>,
trackerInfoPublisher: some Publisher<DetectedRequest, Never>,
dependencies: some AdClickAttributionDependencies,
dateTimeProvider: @escaping () -> Date = Date.init,
logicsProvider: (AdClickAttributionDependencies) -> (AdClickLogicProtocol, AdClickAttributionDetecting) = AdClickAttributionTabExtension.makeAdClickAttribution) {
logicsProvider: (AdClickAttributionDependencies, Bool?) -> (AdClickLogicProtocol, AdClickAttributionDetecting) = AdClickAttributionTabExtension.makeAdClickAttribution) {

self.dependencies = dependencies
self.dateTimeProvider = dateTimeProvider

(self.logic, self.detection) = logicsProvider(dependencies)
// do not enroll users who have CPM disabled
if !CookiePopupProtectionPreferences.shared.isAutoconsentEnabled || !dependencies.privacyConfigurationManager.privacyConfig.isSubfeatureEnabled(AutoconsentSubfeature.filterlistExperiment) {
self.cpmExperimentOn = nil
} else {
self.cpmExperimentOn = AutoconsentFilterlistExperiment.cohort == AutoconsentFilterlistExperiment.test
}
(self.logic, self.detection) = logicsProvider(dependencies, self.cpmExperimentOn)
self.logic.delegate = self

// delay firing up until UserContentController is published
Expand Down Expand Up @@ -166,7 +174,7 @@ final class AdClickAttributionTabExtension: TabExtension {

trackerInfoPublisher
.sink { [weak self] tracker in
self?.logic.onRequestDetected(request: tracker)
self?.logic.onRequestDetected(request: tracker, cpmExperimentOn: self?.cpmExperimentOn)
}
.store(in: &cancellables)
}
Expand Down
2 changes: 1 addition & 1 deletion LocalPackages/DataBrokerProtection/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ let package = Package(
targets: ["DataBrokerProtection"])
],
dependencies: [
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "184.0.1"),
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "184.0.3"),
.package(path: "../SwiftUIExtensions"),
.package(path: "../XPCHelper"),
],
Expand Down
2 changes: 1 addition & 1 deletion LocalPackages/NetworkProtectionMac/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ let package = Package(
.library(name: "VPNAppLauncher", targets: ["VPNAppLauncher"]),
],
dependencies: [
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "184.0.1"),
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "184.0.3"),
.package(url: "https://github.com/airbnb/lottie-spm", exact: "4.4.3"),
.package(path: "../AppLauncher"),
.package(path: "../UDSHelper"),
Expand Down
2 changes: 1 addition & 1 deletion LocalPackages/SubscriptionUI/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ let package = Package(
targets: ["SubscriptionUI"]),
],
dependencies: [
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "184.0.1"),
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "184.0.3"),
.package(path: "../SwiftUIExtensions")
],
targets: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class AdClickAttributionTabExtensionTests: XCTestCase {
contentBlockerRulesScriptPublisher: self.contentBlockerRulesScriptSubj,
trackerInfoPublisher: self.trackerInfoPublisher,
dependencies: dependencies.privacyFeatures.contentBlocking,
dateTimeProvider: { self.now }) { _ in
dateTimeProvider: { self.now }) { _, _ in
(logic: self.logic, detection: self.detection)
}
}
Expand Down Expand Up @@ -671,7 +671,7 @@ class MockAdClickLogic: AdClickLogicProtocol {
}

var onRequestDetected: ((DetectedRequest) -> Void)!
func onRequestDetected(request: DetectedRequest) {
func onRequestDetected(request: DetectedRequest, cpmExperimentOn: Bool? = nil) {
onRequestDetected(request)
}

Expand Down

0 comments on commit b9326eb

Please sign in to comment.