Skip to content

Commit

Permalink
Add FXIOS-10675 [ToS] Firefox iOS: Manage Technical Data during Onboa…
Browse files Browse the repository at this point in the history
…rding and Settings (#23793)

* FXIOS-10675 Firefox iOS: Manage Technical Data during Onboarding and Settings

* Reverted some code
  • Loading branch information
dicarobinho authored Dec 18, 2024
1 parent 956a5a5 commit ae46dac
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 133 deletions.
1 change: 0 additions & 1 deletion BrowserKit/Sources/Shared/AppConstants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ public class AppConstants {
}()

public static let prefSendUsageData = "settings.sendUsageData"
public static let prefSendTechnicalData = "settings.sendTechnicalData"
public static let prefSendCrashReports = "settings.sendCrashReports"
public static let prefSendDailyUsagePing = "settings.sendDailyUsagePing"
public static let prefStudiesToggle = "settings.studiesToggle"
Expand Down
47 changes: 19 additions & 28 deletions firefox-ios/Client/Application/AppLaunchUtil.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,29 @@ class AppLaunchUtil {

DefaultBrowserUtil().processUserDefaultState(isFirstRun: introScreenManager.shouldShowIntroScreen)

TelemetryWrapper.shared.setup(profile: profile)
recordStartUpTelemetry()
// Initialize the feature flag subsystem.
// Among other things, it toggles on and off Nimbus, Contile, Adjust.
// i.e. this must be run before initializing those systems.
LegacyFeatureFlagsManager.shared.initializeDeveloperFeatures(with: profile)

// Need to get "settings.sendCrashReports" this way so that Sentry can be initialized before getting the Profile.
let sendCrashReports = NSUserDefaultsPrefs(prefix: "profile").boolForKey(AppConstants.prefSendCrashReports) ?? true

// For this phase, we should handle terms of service as accepted, in case of app updates.
logger.setup(sendCrashReports: sendCrashReports && (termsOfServiceManager.isAccepted ||
!introScreenManager.shouldShowIntroScreen))
if termsOfServiceManager.isFeatureEnabled {
// Two cases:
// 1. when ToS screen has been presented and user accepted it
// 2. or when ToS screen is not presented because is not fresh install
let isTermsOfServiceAccepted = termsOfServiceManager.isAccepted || !introScreenManager.shouldShowIntroScreen
logger.setup(sendCrashReports: sendCrashReports && isTermsOfServiceAccepted)
if isTermsOfServiceAccepted {
TelemetryWrapper.shared.setup(profile: profile)
TelemetryWrapper.shared.recordStartUpTelemetry()
}
} else {
logger.setup(sendCrashReports: sendCrashReports)
TelemetryWrapper.shared.setup(profile: profile)
TelemetryWrapper.shared.recordStartUpTelemetry()
}

setUserAgent()

Expand All @@ -56,18 +70,11 @@ class AppLaunchUtil {
let conversionValue = ConversionValueUtil(fineValue: 0, coarseValue: .low, logger: logger)
conversionValue.adNetworkAttributionUpdateConversionEvent()

// Initialize the feature flag subsystem.
// Among other things, it toggles on and off Nimbus, Contile, Adjust.
// i.e. this must be run before initializing those systems.
LegacyFeatureFlagsManager.shared.initializeDeveloperFeatures(with: profile)

// Used by share extension to determine if the bookmarks refactor feature flag is enabled
profile.prefs.setBool(LegacyFeatureFlagsManager.shared.isFeatureEnabled(.bookmarksRefactor,
checking: .buildOnly),
forKey: PrefsKeys.IsBookmarksRefactorEnabled)

logger.setup(sendCrashReports: sendCrashReports && !termsOfServiceManager.isFeatureEnabled)

// Start initializing the Nimbus SDK. This should be done after Glean
// has been started.
initializeExperiments()
Expand Down Expand Up @@ -214,22 +221,6 @@ class AppLaunchUtil {
}
}

private func recordStartUpTelemetry() {
let isEnabled: Bool = (profile.prefs.boolForKey(PrefsKeys.UserFeatureFlagPrefs.SponsoredShortcuts) ?? true) &&
(profile.prefs.boolForKey(PrefsKeys.UserFeatureFlagPrefs.TopSiteSection) ?? true)
TelemetryWrapper.recordEvent(category: .information,
method: .view,
object: .sponsoredShortcuts,
extras: [TelemetryWrapper.EventExtraKey.preference.rawValue: isEnabled])

if logger.crashedLastLaunch {
TelemetryWrapper.recordEvent(category: .information,
method: .error,
object: .app,
value: .crashedLastLaunch)
}
}

private func setMenuItems() {
let webViewModel = MenuHelperWebViewModel(searchTitle: .MenuHelperSearchWithFirefox,
findInPageTitle: .MenuHelperFindInPage)
Expand Down
11 changes: 10 additions & 1 deletion firefox-ios/Client/Coordinators/Launch/LaunchCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,20 @@ class LaunchCoordinator: BaseCoordinator,
isFullScreen: Bool) {
let viewController = TermsOfServiceViewController(profile: profile, windowUUID: windowUUID)
viewController.didFinishFlow = { [weak self] in
manager.setAccepted()
guard let self = self else { return }
manager.setAccepted()

let sendTechnicalData = profile.prefs.boolForKey(AppConstants.prefSendUsageData) ?? true
manager.shouldSendTechnicalData(value: sendTechnicalData)
self.profile.prefs.setBool(sendTechnicalData, forKey: AppConstants.prefSendUsageData)

let sendCrashReports = profile.prefs.boolForKey(AppConstants.prefSendCrashReports) ?? true
self.profile.prefs.setBool(sendCrashReports, forKey: AppConstants.prefSendCrashReports)
self.logger.setup(sendCrashReports: sendCrashReports)

TelemetryWrapper.shared.setup(profile: profile)
TelemetryWrapper.shared.recordStartUpTelemetry()

self.parentCoordinator?.didFinishTermsOfService(from: self)
}
viewController.modalPresentationStyle = .fullScreen
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ final class PrivacyPreferencesViewController: UIViewController,
view.setSwitchValue(isOn: self?.profile.prefs.boolForKey(AppConstants.prefSendCrashReports) ?? true)
}

private lazy var technicalDataSwitch: SwitchDetailedView = .build()
private lazy var technicalDataSwitch: SwitchDetailedView = .build { [weak self] view in
view.setSwitchValue(isOn: self?.profile.prefs.boolForKey(AppConstants.prefSendUsageData) ?? true)
}

// MARK: - Initializers
init(
Expand Down Expand Up @@ -163,8 +165,9 @@ final class PrivacyPreferencesViewController: UIViewController,
self?.profile.prefs.setBool(value, forKey: AppConstants.prefSendCrashReports)
}

// TODO: FXIOS-10675 Firefox iOS: Manage Technical Data during Onboarding and Settings
technicalDataSwitch.switchCallback = { _ in }
technicalDataSwitch.switchCallback = { [weak self] value in
self?.profile.prefs.setBool(value, forKey: AppConstants.prefSendUsageData)
}

crashReportsSwitch.learnMoreCallBack = { [weak self] in
self?.presentLink(with: SupportUtils.URLForTopic("mobile-crash-reports"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,36 +178,34 @@ class AppSettingsTableViewController: SettingsTableViewController,
private func setupDataSettings() {
let isTermsOfServiceFeatureEnabled = featureFlags.isFeatureEnabled(.tosFeature, checking: .buildOnly)

let anonymousUsageDataSetting = SendDataSetting(
prefs: profile.prefs,
delegate: settingsDelegate,
theme: themeManager.getCurrentTheme(for: windowUUID),
settingsDelegate: parentCoordinator,
sendDataType: .usageData
)

let studiesSetting = StudiesToggleSetting(
prefs: profile.prefs,
delegate: settingsDelegate,
theme: themeManager.getCurrentTheme(for: windowUUID),
settingsDelegate: parentCoordinator
)

anonymousUsageDataSetting.shouldSendData = { value in
studiesSetting.updateSetting(for: value)
}

// Only add these toggles to the Settings if Terms Of Service feature flag is enabled
if isTermsOfServiceFeatureEnabled {
let sendTechnicalDataSettings = SendDataSetting(
prefs: profile.prefs,
delegate: settingsDelegate,
theme: themeManager.getCurrentTheme(for: windowUUID),
settingsDelegate: parentCoordinator,
sendDataType: .technicalData
title: .SendTechnicalDataSettingTitle,
message: String(format: .SendTechnicalDataSettingMessage,
MozillaName.shortName.rawValue,
AppName.shortName.rawValue),
linkedText: .SendTechnicalDataSettingLink,
prefKey: AppConstants.prefSendUsageData,
a11yId: AccessibilityIdentifiers.Settings.SendData.sendTechnicalDataTitle,
learnMoreURL: SupportUtils.URLForTopic("mobile-technical-and-interaction-data")
)
sendTechnicalDataSettings.shouldSendData = { value in
// TODO: FXIOS-10754 Firefox iOS: Manage Privacy Preferences in Settings - Logic

sendTechnicalDataSettings.shouldSendData = { [weak self] value in
guard let self else { return }
TermsOfServiceManager(prefs: self.profile.prefs).shouldSendTechnicalData(value: value)
studiesSetting.updateSetting(for: value)
}
sendTechnicalDataSetting = sendTechnicalDataSettings

Expand All @@ -216,24 +214,55 @@ class AppSettingsTableViewController: SettingsTableViewController,
delegate: settingsDelegate,
theme: themeManager.getCurrentTheme(for: windowUUID),
settingsDelegate: parentCoordinator,
sendDataType: .dailyUsagePing
title: .SendDailyUsagePingSettingTitle,
message: String(format: .SendDailyUsagePingSettingMessage, MozillaName.shortName.rawValue),
linkedText: .SendDailyUsagePingSettingLink,
prefKey: AppConstants.prefSendDailyUsagePing,
a11yId: AccessibilityIdentifiers.Settings.SendData.sendDailyUsagePingTitle,
learnMoreURL: SupportUtils.URLForTopic("usage-ping-settings-mobile")
)
sendDailyUsagePingSettings.shouldSendData = { value in
// TODO: FXIOS-10754 Firefox iOS: Manage Privacy Preferences in Settings - Logic
// TODO: FXIOS-10469 Firefox iOS: DAU Ping Setting
}
sendDailyUsagePingSetting = sendDailyUsagePingSettings
} else {
let sendAnonymousUsageDataSettings = SendDataSetting(
prefs: profile.prefs,
delegate: settingsDelegate,
theme: themeManager.getCurrentTheme(for: windowUUID),
settingsDelegate: parentCoordinator,
title: .SendUsageSettingTitle,
message: String(format: .SendUsageSettingMessage,
MozillaName.shortName.rawValue,
AppName.shortName.rawValue),
linkedText: .SendUsageSettingLink,
prefKey: AppConstants.prefSendUsageData,
a11yId: AccessibilityIdentifiers.Settings.SendData.sendAnonymousUsageDataTitle,
learnMoreURL: SupportUtils.URLForTopic("adjust")
)

sendAnonymousUsageDataSettings.shouldSendData = { [weak self] value in
guard let self else { return }
TermsOfServiceManager(prefs: self.profile.prefs).shouldSendTechnicalData(value: value)
studiesSetting.updateSetting(for: value)
}
sendAnonymousUsageDataSetting = sendAnonymousUsageDataSettings
}

let sendCrashReportsSettings = SendDataSetting(
prefs: profile.prefs,
delegate: settingsDelegate,
theme: themeManager.getCurrentTheme(for: windowUUID),
settingsDelegate: parentCoordinator,
sendDataType: .crashReports
title: .SendCrashReportsSettingTitle,
message: String(format: .SendCrashReportsSettingMessage, MozillaName.shortName.rawValue),
linkedText: .SendCrashReportsSettingLink,
prefKey: AppConstants.prefSendCrashReports,
a11yId: AccessibilityIdentifiers.Settings.SendData.sendCrashReportsTitle,
learnMoreURL: SupportUtils.URLForTopic("mobile-crash-reports")
)
self.sendCrashReportsSetting = sendCrashReportsSettings

sendAnonymousUsageDataSetting = anonymousUsageDataSetting
studiesToggleSetting = studiesSetting
}

Expand Down Expand Up @@ -399,7 +428,7 @@ class AppSettingsTableViewController: SettingsTableViewController,
}

private func getSupportSettings() -> [SettingSection] {
guard let sendAnonymousUsageDataSetting, let studiesToggleSetting else { return [] }
guard let studiesToggleSetting else { return [] }

var supportSettings = [
ShowIntroductionSetting(settings: self, settingsDelegate: self),
Expand All @@ -418,10 +447,10 @@ class AppSettingsTableViewController: SettingsTableViewController,
)
}

supportSettings.append(sendAnonymousUsageDataSetting)

if let sendTechnicalDataSetting {
supportSettings.append(sendTechnicalDataSetting)
} else if let sendAnonymousUsageDataSetting {
supportSettings.append(sendAnonymousUsageDataSetting)
}

if let sendCrashReportsSetting {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,54 +7,23 @@ import Foundation
import Glean
import Shared

enum SendDataType {
case usageData
case technicalData
case crashReports
case dailyUsagePing
}

class SendDataSetting: BoolSetting {
private weak var settingsDelegate: SupportSettingsDelegate?
private let sendDataType: SendDataType
private var a11yId: String
private var learnMoreURL: URL?

var shouldSendData: ((Bool) -> Void)?

init(prefs: Prefs,
delegate: SettingsDelegate?,
theme: Theme,
settingsDelegate: SupportSettingsDelegate?,
sendDataType: SendDataType) {
var title: String
var message: String
var linkedText: String
var prefKey: String

switch sendDataType {
case .usageData:
title = .SendUsageSettingTitle
message = .SendUsageSettingMessage
linkedText = .SendUsageSettingLink
prefKey = AppConstants.prefSendUsageData
case .technicalData:
title = .SendTechnicalDataSettingTitle
message = String(format: .SendTechnicalDataSettingMessage,
MozillaName.shortName.rawValue,
AppName.shortName.rawValue)
linkedText = .SendTechnicalDataSettingLink
prefKey = AppConstants.prefSendTechnicalData
case .crashReports:
title = .SendCrashReportsSettingTitle
message = .SendCrashReportsSettingMessage
linkedText = .SendCrashReportsSettingLink
prefKey = AppConstants.prefSendCrashReports
case .dailyUsagePing:
title = .SendDailyUsagePingSettingTitle
message = String(format: .SendDailyUsagePingSettingMessage, MozillaName.shortName.rawValue)
linkedText = .SendDailyUsagePingSettingLink
prefKey = AppConstants.prefSendDailyUsagePing
}

title: String,
message: String,
linkedText: String,
prefKey: String,
a11yId: String,
learnMoreURL: URL?) {
let statusText = NSMutableAttributedString()
statusText.append(
NSAttributedString(
Expand All @@ -74,7 +43,8 @@ class SendDataSetting: BoolSetting {
)
)

self.sendDataType = sendDataType
self.a11yId = a11yId
self.learnMoreURL = learnMoreURL
self.settingsDelegate = settingsDelegate
super.init(
prefs: prefs,
Expand All @@ -84,58 +54,25 @@ class SendDataSetting: BoolSetting {
attributedStatusText: statusText
)

setupSettingDidChange(for: sendDataType)
setupSettingDidChange()

// We make sure to set this on initialization, in case the setting is turned off
// in which case, we would to make sure that users are opted out of experiments
Experiments.setTelemetrySetting(prefs.boolForKey(prefKey) ?? true)
}

private func setupSettingDidChange(for sendDataType: SendDataType) {
private func setupSettingDidChange() {
self.settingDidChange = { [weak self] value in
if sendDataType != .crashReports {
// AdjustHelper.setEnabled($0)
DefaultGleanWrapper.shared.setUpload(isEnabled: value)

if !value {
self?.prefs?.removeObjectForKey(PrefsKeys.Usage.profileId)

// set dummy uuid to make sure the previous one is deleted
if let uuid = UUID(uuidString: "beefbeef-beef-beef-beef-beeefbeefbee") {
GleanMetrics.Usage.profileId.set(uuid)
}
}

Experiments.setTelemetrySetting(value)
self?.shouldSendData?(value)
}
self?.shouldSendData?(value)
}
}

override var accessibilityIdentifier: String? {
switch sendDataType {
case .usageData:
return AccessibilityIdentifiers.Settings.SendData.sendAnonymousUsageDataTitle
case .technicalData:
return AccessibilityIdentifiers.Settings.SendData.sendTechnicalDataTitle
case .crashReports:
return AccessibilityIdentifiers.Settings.SendData.sendCrashReportsTitle
case .dailyUsagePing:
return AccessibilityIdentifiers.Settings.SendData.sendDailyUsagePingTitle
}
return a11yId
}

override var url: URL? {
switch sendDataType {
case .usageData:
return SupportUtils.URLForTopic("adjust")
case .technicalData:
return SupportUtils.URLForTopic("mobile-technical-and-interaction-data")
case .crashReports:
return SupportUtils.URLForTopic("mobile-crash-reports")
case .dailyUsagePing:
return SupportUtils.URLForTopic("usage-ping-settings-mobile")
}
return learnMoreURL
}

override func onClick(_ navigationController: UINavigationController?) {
Expand Down
Loading

0 comments on commit ae46dac

Please sign in to comment.