Skip to content
This repository has been archived by the owner on May 10, 2024. It is now read-only.

Commit

Permalink
Fix #1938: Implement P3A on iOS (#6308)
Browse files Browse the repository at this point in the history
  • Loading branch information
soner-yuksel authored Nov 16, 2022
1 parent e080ce0 commit caf52a2
Show file tree
Hide file tree
Showing 27 changed files with 602 additions and 148 deletions.
13 changes: 11 additions & 2 deletions App/iOS/Delegates/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
}

// Check if user has launched the application before and determine if it is a new retention user
if Preferences.General.isFirstLaunch.value, Preferences.General.isNewRetentionUser.value == nil {
Preferences.General.isNewRetentionUser.value = true
if Preferences.General.isFirstLaunch.value, Preferences.Onboarding.isNewRetentionUser.value == nil {
Preferences.Onboarding.isNewRetentionUser.value = true
}

if Preferences.DAU.appRetentionLaunchDate.value == nil {
Expand Down Expand Up @@ -343,6 +343,15 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
.didFinishLaunching(options: launchOptions ?? [:])
)

// DAU may not have pinged on the first launch so weekOfInstallation pref may not be set yet
if let weekOfInstall = Preferences.DAU.weekOfInstallation.value ??
Preferences.DAU.installationDate.value?.mondayOfCurrentWeekFormatted {
braveCore.initializeP3AService(
forChannel: AppConstants.buildChannel.serverChannelParam,
weekOfInstall: weekOfInstall
)
}

return shouldPerformAdditionalDelegateHandling
}

Expand Down
3 changes: 2 additions & 1 deletion Client/Frontend/Browser/BrowserViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1120,9 +1120,10 @@ public class BrowserViewController: UIViewController {
presentOnboardingIntro()

// Full Screen Callout Presentation
// Priority: VPN - Default Browser - Rewards - Sync
// Priority: P3A - VPN - Default Browser - Rewards
// TODO: Remove the dispatch after with a proper fix and fix calling present functions before super.viewDidAppear
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
self.presentP3AScreenCallout()
self.presentVPNAlertCallout()
self.presentDefaultBrowserScreenCallout()
self.presentBraveRewardsScreenCallout()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ extension BrowserViewController {

func showBraveRewardsPanel() {
if !Preferences.FullScreenCallout.rewardsCalloutCompleted.value,
Preferences.General.isNewRetentionUser.value == true,
Preferences.Onboarding.isNewRetentionUser.value == true,
!Preferences.Rewards.rewardsToggledOnce.value {

let controller = OnboardingRewardsAgreementViewController()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import SwiftKeychainWrapper
import SwiftUI
import BraveVPN
import Onboarding
import SafariServices

// MARK: - Callouts

Expand All @@ -29,6 +30,51 @@ extension BrowserViewController {
present(controller, animated: false)
}
}

func presentP3AScreenCallout() {
if Preferences.DebugFlag.skipNTPCallouts == true || isOnboardingOrFullScreenCalloutPresented { return }

if presentedViewController != nil || !FullScreenCalloutManager.shouldShowDefaultBrowserCallout(calloutType: .p3a) {
return
}

let onboardingP3ACalloutController = Welcome3PAViewController().then {
$0.isModalInPresentation = true
$0.modalPresentationStyle = .overFullScreen
}

let state = WelcomeViewCalloutState.p3a(
info: WelcomeViewCalloutState.WelcomeViewDefaultBrowserDetails(
title: Strings.Callout.p3aCalloutTitle,
toggleTitle: Strings.Callout.p3aCalloutToggleTitle,
details: Strings.Callout.p3aCalloutDescription,
linkDescription: Strings.Callout.p3aCalloutLinkTitle,
primaryButtonTitle: Strings.done,
toggleAction: { [weak self] isOn in
self?.braveCore.p3aUtils.isP3AEnabled = isOn
},
linkAction: { url in
let p3aLearnMoreController = SFSafariViewController(url: BraveUX.braveP3ALearnMoreURL, configuration: .init())
p3aLearnMoreController.modalPresentationStyle = .currentContext

onboardingP3ACalloutController.present(p3aLearnMoreController, animated: true)
},
primaryButtonAction: { [weak self] in
Preferences.Onboarding.p3aOnboardingShown.value = true

self?.isOnboardingOrFullScreenCalloutPresented = true
self?.dismiss(animated: false)
}
)
)

onboardingP3ACalloutController.setLayoutState(state: state)

if !isOnboardingOrFullScreenCalloutPresented {
braveCore.p3aUtils.isNoticeAcknowledged = true
present(onboardingP3ACalloutController, animated: false)
}
}

func presentVPNAlertCallout() {
if Preferences.DebugFlag.skipNTPCallouts == true || isOnboardingOrFullScreenCalloutPresented { return }
Expand Down Expand Up @@ -79,7 +125,7 @@ extension BrowserViewController {
details: Strings.Callout.defaultBrowserCalloutDescription,
primaryButtonTitle: Strings.Callout.defaultBrowserCalloutPrimaryButtonTitle,
secondaryButtonTitle: Strings.Callout.defaultBrowserCalloutSecondaryButtonTitle,
primaryAction: { [weak self] in
primaryButtonAction: { [weak self] in
guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else {
return
}
Expand All @@ -90,13 +136,13 @@ extension BrowserViewController {
UIApplication.shared.open(settingsUrl)
self?.dismiss(animated: false)
},
secondaryAction: { [weak self] in
secondaryButtonAction: { [weak self] in
self?.isOnboardingOrFullScreenCalloutPresented = true

self?.dismiss(animated: false)
}
)
)
), p3aUtilities: braveCore.p3aUtils
)

if !isOnboardingOrFullScreenCalloutPresented {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import SwiftUI
import BraveUI
import BraveShared
import Data
import Onboarding

extension BrowserViewController {
func presentCookieNotificationBlockingCalloutIfNeeded() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ extension BrowserViewController {
// 1. User is brand new
// 2. User hasn't completed onboarding
if Preferences.Onboarding.basicOnboardingCompleted.value != OnboardingState.completed.rawValue,
Preferences.General.isNewRetentionUser.value == true {
let onboardingController = WelcomeViewController()
Preferences.Onboarding.isNewRetentionUser.value == true {
let onboardingController = WelcomeViewController(p3aUtilities: braveCore.p3aUtils)
onboardingController.modalPresentationStyle = .fullScreen
parentController.present(onboardingController, animated: false)
isOnboardingOrFullScreenCalloutPresented = true
Expand All @@ -58,7 +58,7 @@ extension BrowserViewController {
Preferences.DebugFlag.skipNTPCallouts != true {

if !Preferences.FullScreenCallout.omniboxCalloutCompleted.value,
Preferences.General.isNewRetentionUser.value == true {
Preferences.Onboarding.isNewRetentionUser.value == true {
presentOmniBoxOnboarding()
addNTPTutorialPage()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ extension BrowserViewController {
!Preferences.General.onboardingAdblockPopoverShown.value,
!benchmarkNotificationPresented,
!Preferences.AppState.backgroundedCleanly.value,
Preferences.General.isNewRetentionUser.value == true,
Preferences.Onboarding.isNewRetentionUser.value == true,
!topToolbar.inOverlayMode,
!isTabTrayActive,
selectedTab.webView?.scrollView.isDragging == false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,8 @@ extension BrowserViewController: TopToolbarDelegate {
profile: self.profile,
tabManager: self.tabManager,
feedDataSource: self.feedDataSource,
historyAPI: self.braveCore.historyAPI
historyAPI: self.braveCore.historyAPI,
p3aUtilities: self.braveCore.p3aUtils
)
let container = SettingsNavigationController(rootViewController: shieldsAndPrivacy)
container.isModalInPresentation = true
Expand Down
39 changes: 0 additions & 39 deletions Client/Frontend/ClientPreferences.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ extension Preferences {
final public class General {
/// Whether this is the first time user has ever launched Brave after intalling. *Should never be set to `true` manually!*
public static let isFirstLaunch = Option<Bool>(key: "general.first-launch", default: true)
/// Whether this is a new user who installed the application after onboarding retention updates
public static let isNewRetentionUser = Option<Bool?>(key: "general.new-retention", default: nil)
/// Whether or not to save logins in Brave
static let saveLogins = Option<Bool>(key: "general.save-logins", default: true)
/// Whether or not to block popups from websites automaticaly
Expand Down Expand Up @@ -95,43 +93,6 @@ extension Preferences {
static let isUsingBottomBar = Option<Bool>(key: "general.bottom-bar", default: false)
}

final public class FullScreenCallout {
/// Whether the block cookie consent notices callout is shown.
static let blockCookieConsentNoticesCalloutCompleted =
Option<Bool>(key: "fullScreenCallout.full-screen-cookie-consent-notices-callout-completed", default: false)

/// Whether the vpn callout is shown.
static let vpnCalloutCompleted =
Option<Bool>(key: "fullScreenCallout.full-screen-vpn-callout-completed", default: false)

/// Whether the rewards callout is shown.
static let rewardsCalloutCompleted =
Option<Bool>(key: "fullScreenCallout.full-screen-rewards-callout-completed", default: false)

/// Whether the whats new callout should be shown.
static let whatsNewCalloutOptIn =
Option<Bool>(key: "fullScreenCallout.full-screen-whats-new-callout-completed", default: false)

/// Whether the ntp callout is shown.
static let ntpCalloutCompleted =
Option<Bool>(key: "fullScreenCallout.full-screen-ntp-callout-completed", default: false)

/// Whether the omnibox callout is shown.
static let omniboxCalloutCompleted =
Option<Bool>(key: "fullScreenCallout.full-screen-omnibox-callout-completed", default: false)
}

final public class DefaultBrowserIntro {
/// Whether the default browser onboarding completed. This can happen by opening app settings or after the user
/// dismissed the intro screen enough amount of times.
static let completed =
Option<Bool>(key: "defaultBrowserIntro.intro-completed", default: false)

/// Whether system notification showed or not
static let defaultBrowserNotificationScheduled =
Option<Bool>(key: "general.default-browser-notification-scheduled", default: false)
}

final public class Search {
/// Whether or not to show suggestions while the user types
static let showSuggestions = Option<Bool>(key: "search.show-suggestions", default: false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,25 @@ class BraveShieldsAndPrivacySettingsController: TableViewController {
let tabManager: TabManager
let feedDataSource: FeedDataSource
let historyAPI: BraveHistoryAPI
let p3aUtilities: BraveP3AUtils

private let cookieConsentNoticesRowUUID = UUID()
private var filterListsSubscription: AnyCancellable?
private var currentCookieConsentNoticeBlockingState: Bool

init(profile: Profile, tabManager: TabManager, feedDataSource: FeedDataSource, historyAPI: BraveHistoryAPI) {
init(
profile: Profile,
tabManager: TabManager,
feedDataSource: FeedDataSource,
historyAPI: BraveHistoryAPI,
p3aUtilities: BraveP3AUtils
) {
self.profile = profile
self.tabManager = tabManager
self.feedDataSource = feedDataSource
self.historyAPI = historyAPI

self.p3aUtilities = p3aUtilities

self.currentCookieConsentNoticeBlockingState = FilterListResourceDownloader.shared.isEnabled(
for: FilterList.cookieConsentNoticesComponentID
)
Expand Down Expand Up @@ -264,6 +273,16 @@ class BraveShieldsAndPrivacySettingsController: TableViewController {
}()

private lazy var otherSettingsSection: Section = {
let p3aRow = Row.boolRow(
title: Strings.P3A.settingTitle,
detailText: Strings.P3A.settingSubtitle,
toggleValue: p3aUtilities.isP3AEnabled,
valueChange: { [unowned self] isOn in
p3aUtilities.isP3AEnabled = isOn
},
cellReuseId: "p3a"
)

var section = Section(
header: .title(Strings.otherPrivacySettingsSection),
rows: [
Expand All @@ -289,6 +308,7 @@ class BraveShieldsAndPrivacySettingsController: TableViewController {
)
)
}
section.rows.append(p3aRow)

return section
}()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ import BraveShared
import UIKit
import BraveUI
import Onboarding
import BraveCore

class RetentionPreferencesDebugMenuViewController: TableViewController {
private let p3aUtilities: BraveP3AUtils

init() {
init(p3aUtilities: BraveP3AUtils) {
self.p3aUtilities = p3aUtilities
super.init(style: .insetGrouped)
}

Expand Down Expand Up @@ -52,7 +55,7 @@ class RetentionPreferencesDebugMenuViewController: TableViewController {
.init(
text: "Start Onboarding",
selection: { [unowned self] in
let onboardingController = WelcomeViewController()
let onboardingController = WelcomeViewController(state: .loading, p3aUtilities: self.p3aUtilities)
onboardingController.modalPresentationStyle = .fullScreen

present(onboardingController, animated: false)
Expand Down Expand Up @@ -104,11 +107,11 @@ class RetentionPreferencesDebugMenuViewController: TableViewController {
.boolRow(
title: "Retention User",
detailText: "Flag showing if the user installed the application after new onboarding is added.",
toggleValue: Preferences.General.isNewRetentionUser.value ?? false,
toggleValue: Preferences.Onboarding.isNewRetentionUser.value ?? false,
valueChange: {
if $0 {
let status = $0
Preferences.General.isNewRetentionUser.value = status
Preferences.Onboarding.isNewRetentionUser.value = status
}
},
cellReuseId: "RetentionUserCell"),
Expand Down
16 changes: 14 additions & 2 deletions Client/Frontend/Settings/SettingsViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class SettingsViewController: TableViewController {
private let passwordAPI: BravePasswordAPI
private let syncAPI: BraveSyncAPI
private let syncProfileServices: BraveSyncProfileServiceIOS
private let p3aUtilities: BraveP3AUtils
private let keyringStore: KeyringStore?
private let cryptoStore: CryptoStore?
private let windowProtection: WindowProtection?
Expand Down Expand Up @@ -74,6 +75,7 @@ class SettingsViewController: TableViewController {
self.passwordAPI = braveCore.passwordAPI
self.syncAPI = braveCore.syncAPI
self.syncProfileServices = braveCore.syncProfileService
self.p3aUtilities = braveCore.p3aUtils
self.keyringStore = keyringStore
self.cryptoStore = cryptoStore

Expand Down Expand Up @@ -205,7 +207,9 @@ class SettingsViewController: TableViewController {
profile: self.profile,
tabManager: self.tabManager,
feedDataSource: self.feedDataSource,
historyAPI: self.historyAPI)
historyAPI: self.historyAPI,
p3aUtilities: self.p3aUtilities
)
self.navigationController?.pushViewController(controller, animated: true)
}, image: UIImage(named: "settings-shields", in: .module, compatibleWith: nil)!, accessory: .disclosureIndicator)
],
Expand Down Expand Up @@ -659,6 +663,14 @@ class SettingsViewController: TableViewController {
selection: { [unowned self] in
self.displayBraveSearchDebugMenu()
}, accessory: .disclosureIndicator, cellClass: MultilineValue1Cell.self),
Row(
text: "View Brave Histogram (p3a) Logs",
selection: { [unowned self] in
let histogramsController = self.p3aUtilities.histogramsController().then {
$0.title = "Histograms (p3a)"
}
self.navigationController?.pushViewController(histogramsController, animated: true)
}, accessory: .disclosureIndicator, cellClass: MultilineValue1Cell.self),
Row(
text: "VPN Logs",
selection: { [unowned self] in
Expand All @@ -667,7 +679,7 @@ class SettingsViewController: TableViewController {
Row(
text: "Retention Preferences Debug Menu",
selection: { [unowned self] in
self.navigationController?.pushViewController(RetentionPreferencesDebugMenuViewController(), animated: true)
self.navigationController?.pushViewController(RetentionPreferencesDebugMenuViewController(p3aUtilities: p3aUtilities), animated: true)
}, accessory: .disclosureIndicator, cellClass: MultilineValue1Cell.self),
Row(
text: "Load all QA Links",
Expand Down
3 changes: 2 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -352,14 +352,15 @@ let package = Package(
"BraveCore",
"Fuzi",
"Storage",
"Growth",
.product(name: "Lottie", package: "lottie-ios")
],
resources: [
.copy("LottieAssets/onboarding-ads.json"),
.copy("LottieAssets/onboarding-rewards.json"),
.copy("LottieAssets/onboarding-shields.json"),
.copy("Welcome/Resources/disconnect-entitylist.json"),
.copy("ProductNotifications/blocking-summary.json")
.copy("ProductNotifications/Resources/blocking-summary.json")
],
plugins: ["LoggerPlugin"]
),
Expand Down
Loading

0 comments on commit caf52a2

Please sign in to comment.