Skip to content

Commit

Permalink
Merges the latest from main
Browse files Browse the repository at this point in the history
  • Loading branch information
diegoreymendez committed Aug 5, 2024
2 parents b241034 + 11839fd commit 921f049
Show file tree
Hide file tree
Showing 161 changed files with 10,034 additions and 837 deletions.
57 changes: 57 additions & 0 deletions .maestro/release_tests/application-lock.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# application-lock.yaml
appId: com.duckduckgo.mobile.ios
tags:
- release

---

# Set up
- runFlow:
file: ../shared/setup.yaml

- tapOn: "Settings"
- scrollUntilVisible:
element: "General"
direction: DOWN
- tapOn: "General"

- tapOn:
text: "0"
index: "0"

- stopApp

- launchApp

- assertVisible: "Unlock DuckDuckGo."
- inputText: "password"
- pressKey: Enter

- assertVisible:
id: "searchEntry"
- tapOn:
id: "searchEntry"
- inputText: "https://privacy-test-pages.site"
- pressKey: Enter

# Manage onboarding
- runFlow:
file: ../shared/onboarding_browsing.yaml

- tapOn: "Browsing Menu"
- tapOn: "Settings"
- scrollUntilVisible:
element: "General"
direction: DOWN
- tapOn: "General"

- tapOn:
text: "1"
index: "0"


- stopApp

- launchApp

- assertVisible: "Privacy Test Pages"
60 changes: 60 additions & 0 deletions .maestro/release_tests/tabswitcher.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# tabswitcher.yaml
appId: com.duckduckgo.mobile.ios
tags:
- release

---

# Set up
- runFlow:
file: ../shared/setup.yaml

# Load Site
- assertVisible:
id: "searchEntry"
- tapOn:
id: "searchEntry"
- inputText: "https://privacy-test-pages.site"
- pressKey: Enter

# Manage onboarding
- runFlow:
file: ../shared/onboarding_browsing.yaml

- assertVisible: ".*Privacy Test Pages.*"

# Add tab
- assertVisible: Tab Switcher
- tapOn: Tab Switcher
- assertVisible: ".*Privacy Test Pages.*"
- assertVisible:
id: "Add"
- tapOn:
id: "Add"
- assertVisible:
id: "searchEntry"
- tapOn:
id: "searchEntry"
- inputText: "https://www.search-company.site"
- pressKey: Enter
- assertVisible: "Search engine"

# Bookmark all
- assertVisible: Tab Switcher
- tapOn: Tab Switcher
- tapOn: "Add all tabs as bookmarks"
- assertVisible: "Bookmark All Tabs?"
- tapOn: "Bookmark"

# can't really tell if it works, but at least it won't crash
- tapOn: "Toggle between grid and list view"

# Check bookmarks were added
- tapOn: "Done"

- tapOn: "Browsing menu"
- tapOn: "Bookmarks"
- assertVisible: "Privacy Test Pages - Home"
- assertVisible: "Ad Click Flow"


21 changes: 17 additions & 4 deletions Core/BookmarksStateValidation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,23 @@ import CoreData
import Bookmarks
import Persistence

public class BookmarksStateValidation {
public protocol BookmarksStateValidation {

func validateInitialState(context: NSManagedObjectContext,
validationError: BookmarksStateValidator.ValidationError) -> Bool

func validateBookmarksStructure(context: NSManagedObjectContext)
}

public class BookmarksStateValidator: BookmarksStateValidation {

enum Constants {
static let bookmarksDBIsInitialized = "bookmarksDBIsInitialized"
}

public enum ValidationError {
case bookmarksStructureLost
case bookmarksStructureNotRecovered
case bookmarksStructureBroken(additionalParams: [String: String])
case validatorError(Error)
}
Expand All @@ -43,18 +52,22 @@ public class BookmarksStateValidation {
self.errorHandler = errorHandler
}

public func validateInitialState(context: NSManagedObjectContext) {
guard keyValueStore.object(forKey: Constants.bookmarksDBIsInitialized) != nil else { return }
public func validateInitialState(context: NSManagedObjectContext,
validationError: ValidationError) -> Bool {
guard keyValueStore.object(forKey: Constants.bookmarksDBIsInitialized) != nil else { return true }

let fetch = BookmarkEntity.fetchRequest()
do {
let count = try context.count(for: fetch)
if count == 0 {
errorHandler(.bookmarksStructureLost)
errorHandler(validationError)
return false
}
} catch {
errorHandler(.validatorError(error))
}

return true
}

public func validateBookmarksStructure(context: NSManagedObjectContext) {
Expand Down
11 changes: 9 additions & 2 deletions Core/LegacyBookmarksStoreMigration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,14 @@ public class LegacyBookmarksStoreMigration {
}
} else {
// Initialize structure if needed
BookmarkUtils.prepareLegacyFoldersStructure(in: context)
do {
try BookmarkUtils.prepareLegacyFoldersStructure(in: context)
} catch {
Pixel.fire(pixel: .debugBookmarksInitialStructureQueryFailed, error: error)
Thread.sleep(forTimeInterval: 1)
fatalError("Could not prepare Bookmarks DB structure")
}

if context.hasChanges {
do {
try context.save(onErrorFire: .bookmarksCouldNotPrepareDatabase)
Expand Down Expand Up @@ -178,7 +185,7 @@ public class LegacyBookmarksStoreMigration {
} catch {
destination.reset()

BookmarkUtils.prepareLegacyFoldersStructure(in: destination)
try? BookmarkUtils.prepareLegacyFoldersStructure(in: destination)
do {
try destination.save(onErrorFire: .bookmarksMigrationCouldNotPrepareDatabaseOnFailedMigration)
} catch {
Expand Down
4 changes: 4 additions & 0 deletions Core/Pixel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ public struct PixelParameters {

// Autofill
public static let countBucket = "count_bucket"

// Privacy Dashboard
public static let daysSinceInstall = "daysSinceInstall"
public static let fromOnboarding = "from_onboarding"
}

public struct PixelValues {
Expand Down
78 changes: 49 additions & 29 deletions Core/PixelEvent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ extension Pixel {
case forgetAllDataCleared

case privacyDashboardOpened

case privacyDashboardFirstTimeOpenedUnique

case dashboardProtectionAllowlistAdd
case dashboardProtectionAllowlistRemove

Expand Down Expand Up @@ -142,18 +143,27 @@ extension Pixel {
case onboardingIntroShownUnique
case onboardingIntroComparisonChartShownUnique
case onboardingIntroChooseBrowserCTAPressed

case daxDialogsSerp
case daxDialogsWithoutTrackers
case onboardingContextualSearchOptionTappedUnique
case onboardingContextualSearchCustomUnique
case onboardingContextualSiteOptionTappedUnique
case onboardingContextualSiteCustomUnique
case onboardingContextualSecondSiteVisitUnique
case onboardingContextualTrySearchUnique
case onboardingContextualTryVisitSiteUnique

case daxDialogsSerpUnique
case daxDialogsWithoutTrackersUnique
case daxDialogsWithoutTrackersFollowUp
case daxDialogsWithTrackers
case daxDialogsSiteIsMajor
case daxDialogsSiteOwnedByMajor
case daxDialogsHidden
case daxDialogsFireEducationShown
case daxDialogsFireEducationConfirmed
case daxDialogsFireEducationCancelled

case daxDialogsWithTrackersUnique
case daxDialogsSiteIsMajorUnique
case daxDialogsSiteOwnedByMajorUnique
case daxDialogsHiddenUnique
case daxDialogsFireEducationShownUnique
case daxDialogsFireEducationConfirmedUnique
case daxDialogsFireEducationCancelledUnique
case daxDialogsEndOfJourneyTabUnique
case daxDialogsEndOfJourneyNewTabUnique

case widgetsOnboardingCTAPressed
case widgetsOnboardingDeclineOptionPressed
case widgetsOnboardingMovedToBackground
Expand Down Expand Up @@ -513,7 +523,9 @@ extension Pixel {
case adAttributionLogicWrongVendorOnSuccessfulCompilation
case adAttributionLogicWrongVendorOnFailedCompilation

case debugBookmarksInitialStructureQueryFailed
case debugBookmarksStructureLost
case debugBookmarksStructureNotRecovered
case debugBookmarksInvalidRoots
case debugBookmarksValidationFailed

Expand Down Expand Up @@ -589,8 +601,6 @@ extension Pixel {
case syncDeleteAccountError
case syncLoginExistingAccountError

case syncWrongEnvironment

case swipeTabsUsedDaily
case swipeToOpenNewTab

Expand Down Expand Up @@ -759,7 +769,8 @@ extension Pixel.Event {
case .forgetAllDataCleared: return "mf_dc"

case .privacyDashboardOpened: return "mp"

case .privacyDashboardFirstTimeOpenedUnique: return "m_privacy_dashboard_first_time_used_unique"

case .dashboardProtectionAllowlistAdd: return "mp_wla"
case .dashboardProtectionAllowlistRemove: return "mp_wlr"

Expand Down Expand Up @@ -865,18 +876,27 @@ extension Pixel.Event {
case .onboardingIntroShownUnique: return "m_preonboarding_intro_shown_unique"
case .onboardingIntroComparisonChartShownUnique: return "m_preonboarding_comparison_chart_shown_unique"
case .onboardingIntroChooseBrowserCTAPressed: return "m_preonboarding_choose_browser_pressed"

case .daxDialogsSerp: return "m_dx_s"
case .daxDialogsWithoutTrackers: return "m_dx_wo"
case .onboardingContextualSearchOptionTappedUnique: return "m_onboarding_search_option_tapped_unique"
case .onboardingContextualSiteOptionTappedUnique: return "m_onboarding_visit_site_option_tapped_unique"
case .onboardingContextualSecondSiteVisitUnique: return "m_second_sitevisit_unique"
case .onboardingContextualSearchCustomUnique: return "m_onboarding_search_custom_unique"
case .onboardingContextualSiteCustomUnique: return "m_onboarding_visit_site_custom_unique"
case .onboardingContextualTrySearchUnique: return "m_dx_try_a_search_unique"
case .onboardingContextualTryVisitSiteUnique: return "m_dx_try_visit_site_unique"

case .daxDialogsSerpUnique: return "m_dx_s_unique"
case .daxDialogsWithoutTrackersUnique: return "m_dx_wo_unique"
case .daxDialogsWithoutTrackersFollowUp: return "m_dx_wof"
case .daxDialogsWithTrackers: return "m_dx_wt"
case .daxDialogsSiteIsMajor: return "m_dx_sm"
case .daxDialogsSiteOwnedByMajor: return "m_dx_so"
case .daxDialogsHidden: return "m_dx_h"
case .daxDialogsFireEducationShown: return "m_dx_fe_s"
case .daxDialogsFireEducationConfirmed: return "m_dx_fe_co"
case .daxDialogsFireEducationCancelled: return "m_dx_fe_ca"

case .daxDialogsWithTrackersUnique: return "m_dx_wt_unique"
case .daxDialogsSiteIsMajorUnique: return "m_dx_sm_unique"
case .daxDialogsSiteOwnedByMajorUnique: return "m_dx_so_unique"
case .daxDialogsHiddenUnique: return "m_dx_h_unique"
case .daxDialogsFireEducationShownUnique: return "m_dx_fe_s_unique"
case .daxDialogsFireEducationConfirmedUnique: return "m_dx_fe_co_unique"
case .daxDialogsFireEducationCancelledUnique: return "m_dx_fe_ca_unique"
case .daxDialogsEndOfJourneyTabUnique: return "m_dx_end_tab_unique"
case .daxDialogsEndOfJourneyNewTabUnique: return "m_dx_end_new_tab_unique"

case .widgetsOnboardingCTAPressed: return "m_o_w_a"
case .widgetsOnboardingDeclineOptionPressed: return "m_o_w_d"
case .widgetsOnboardingMovedToBackground: return "m_o_w_b"
Expand Down Expand Up @@ -1210,8 +1230,10 @@ extension Pixel.Event {
return "m_compilation_result_\(result)_time_\(waitTime)_state_\(appState)"

case .emailAutofillKeychainError: return "m_email_autofill_keychain_error"


case .debugBookmarksInitialStructureQueryFailed: return "m_d_bookmarks-initial-structure-query-failed"
case .debugBookmarksStructureLost: return "m_d_bookmarks_structure_lost"
case .debugBookmarksStructureNotRecovered: return "m_d_bookmarks_structure_not_recovered"
case .debugBookmarksInvalidRoots: return "m_d_bookmarks_invalid_roots"
case .debugBookmarksValidationFailed: return "m_d_bookmarks_validation_failed"

Expand Down Expand Up @@ -1295,8 +1317,6 @@ extension Pixel.Event {
case .syncDeleteAccountError: return "m_d_sync_delete_account_error"
case .syncLoginExistingAccountError: return "m_d_sync_login_existing_account_error"

case .syncWrongEnvironment: return "m_d_sync_wrong_environment_u"

case .swipeTabsUsedDaily: return "m_swipe-tabs-used-daily"
case .swipeToOpenNewTab: return "m_addressbar_swipe_new_tab"

Expand Down
16 changes: 13 additions & 3 deletions Core/TimerInterface.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,25 @@ public protocol TimerInterface: AnyObject {
extension Timer: TimerInterface {}

public protocol TimerCreating: AnyObject {
func makeTimer(withTimeInterval interval: TimeInterval, repeats: Bool, block: @escaping @Sendable (TimerInterface) -> Void) -> TimerInterface
func makeTimer(withTimeInterval interval: TimeInterval, repeats: Bool, on runLoop: RunLoop, block: @escaping @Sendable (TimerInterface) -> Void) -> TimerInterface
}

public extension TimerCreating {

func makeTimer(withTimeInterval interval: TimeInterval, repeats: Bool, block: @escaping @Sendable (TimerInterface) -> Void) -> TimerInterface {
makeTimer(withTimeInterval: interval, repeats: repeats, on: .main, block: block)
}

}

public final class TimerFactory: TimerCreating {

public init() {}

public func makeTimer(withTimeInterval interval: TimeInterval, repeats: Bool, block: @escaping @Sendable (TimerInterface) -> Void) -> TimerInterface {
Timer.scheduledTimer(withTimeInterval: interval, repeats: repeats, block: block)
public func makeTimer(withTimeInterval interval: TimeInterval, repeats: Bool, on runLoop: RunLoop, block: @escaping @Sendable (TimerInterface) -> Void) -> TimerInterface {
let timer = Timer(timeInterval: interval, repeats: repeats, block: block)
runLoop.add(timer, forMode: .common)
return timer
}

}
7 changes: 7 additions & 0 deletions Core/UserDefaultsPropertyWrapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,12 @@ public struct UserDefaultsWrapper<T> {
case daxBrowsingMajorTrackingSiteShown = "com.duckduckgo.ios.daxOnboardingBrowsingMajorTrackingSiteShown"
case daxBrowsingOwnedByMajorTrackingSiteShown = "com.duckduckgo.ios.daxOnboardingBrowsingOwnedByMajorTrackingSiteShown"
case daxFireButtonEducationShownOrExpired = "com.duckduckgo.ios.daxfireButtonEducationShownOrExpired"
case daxFireMessageExperimentShown = "com.duckduckgo.ios.fireMessageShown"
case fireButtonPulseDateShown = "com.duckduckgo.ios.fireButtonPulseDateShown"
case privacyButtonPulseShown = "com.duckduckgo.ios.privacyButtonPulseShown"
case daxBrowsingFinalDialogShown = "com.duckduckgo.ios.daxOnboardingFinalDialogSeen"
case daxLastVisitedOnboardingWebsite = "com.duckduckgo.ios.daxOnboardingLastVisitedWebsite"
case daxLastShownContextualOnboardingDialogType = "com.duckduckgo.ios.daxLastShownContextualOnboardingDialogType"

case notFoundCache = "com.duckduckgo.ios.favicons.notFoundCache"
case faviconSizeNeedsMigration = "com.duckduckgo.ios.favicons.sizeNeedsMigration"
Expand Down Expand Up @@ -156,6 +161,8 @@ public struct UserDefaultsWrapper<T> {

case newTabPageSectionsSettings = "com.duckduckgo.ios.newTabPage.sections.settings"
case newTabPageShortcutsSettings = "com.duckduckgo.ios.newTabPage.shortcuts.settings"
case newTabPageIntroMessageEnabled = "com.duckduckgo.ios.newTabPage.introMessageEnabled"
case newTabPageIntroMessageSeenCount = "com.duckduckgo.ios.newTabPage.introMessageSeenCount"

// Debug keys

Expand Down
Loading

0 comments on commit 921f049

Please sign in to comment.