Skip to content

[iOS] Add ability to access developer options menu in official builds #22760

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

Merged
merged 1 commit into from
Mar 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions build/commands/lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ const Config = function () {
this.useBraveHermeticToolchain = this.rbeService.includes('.brave.com:')
this.brave_services_key_id = getEnvConfig(['brave_services_key_id']) || ''
this.service_key_aichat = getEnvConfig(['service_key_aichat']) || ''
this.braveIOSDeveloperOptionsCode = getEnvConfig(['brave_ios_developer_options_code']) || ''
}

Config.prototype.isReleaseBuild = function () {
Expand Down Expand Up @@ -651,6 +652,8 @@ Config.prototype.buildArgs = function () {
args.ios_enable_credential_provider_extension = true
args.ios_enable_widget_kit_extension = false

args.brave_ios_developer_options_code = this.braveIOSDeveloperOptionsCode

// This is currently being flipped on and off by the Chromium team to test
// however it causes crashes for us at launch. Check `ios/features.gni`
// in the future to see if this is no longer needed
Expand Down
2 changes: 2 additions & 0 deletions ios/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import("//brave/ios/browser/api/certificate/headers.gni")
import("//brave/ios/browser/api/credential_provider/headers.gni")
import("//brave/ios/browser/api/de_amp/headers.gni")
import("//brave/ios/browser/api/debounce/headers.gni")
import("//brave/ios/browser/api/developer_options_code/headers.gni")
import("//brave/ios/browser/api/favicon/headers.gni")
import("//brave/ios/browser/api/features/headers.gni")
import("//brave/ios/browser/api/ipfs/headers.gni")
Expand Down Expand Up @@ -111,6 +112,7 @@ brave_core_public_headers += browser_api_web_ui_public_headers
brave_core_public_headers += brave_services_key_public_headers
brave_core_public_headers += browser_api_features_public_headers
brave_core_public_headers += credential_provider_public_headers
brave_core_public_headers += developer_options_code_public_headers

action("brave_core_umbrella_header") {
script = "//build/config/ios/generate_umbrella_header.py"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,6 @@
ReferencedContainer = "container:Client.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<EnvironmentVariables>
<EnvironmentVariable
key = "OS_ACTIVITY_MODE"
value = "${DEBUG_ACTIVITY_MODE}"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
Expand Down
16 changes: 10 additions & 6 deletions ios/brave-ios/App/iOS/Delegates/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import Preferences
import PrivateCDN
import RuntimeWarnings
import SDWebImage
import Shared
@_spi(AppLaunch) import Shared
import Storage
import StoreKit
import UserAgent
Expand Down Expand Up @@ -55,13 +55,17 @@ class AppDelegate: UIResponder, UIApplicationDelegate {

// Application Constants must be initialized first
#if BRAVE_CHANNEL_RELEASE
AppConstants.buildChannel = .release
AppConstants.setBuildChannel(.release)
#elseif BRAVE_CHANNEL_BETA
AppConstants.buildChannel = .beta
AppConstants.setBuildChannel(.beta)
#elseif BRAVE_CHANNEL_NIGHTLY
AppConstants.buildChannel = .nightly
AppConstants.setBuildChannel(.nightly)
#elseif BRAVE_CHANNEL_DEBUG
AppConstants.buildChannel = .debug
AppConstants.setBuildChannel(.debug)
#endif

#if OFFICIAL_BUILD
AppConstants.setOfficialBuild(true)
#endif

AppState.shared.state = .launching(options: launchOptions ?? [:], active: false)
Expand Down Expand Up @@ -257,7 +261,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
// 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,
AppConstants.buildChannel != .debug
AppConstants.isOfficialBuild
{
AppState.shared.braveCore.initializeP3AService(
forChannel: AppConstants.buildChannel.serverChannelParam,
Expand Down
32 changes: 17 additions & 15 deletions ios/brave-ios/App/iOS/Delegates/AppState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -152,40 +152,42 @@ public class AppState {
#endif
}

let isLoggingAccessible =
!AppConstants.isOfficialBuild || Preferences.Debug.developerOptionsEnabled.value

let level: OSLogType = {
switch severity {
case .fatal: return .fault
case .error: return .error
// No `.warning` level exists for OSLogType. os_Log.warning is an alias for `.error`.
case .warning: return .error
case .info: return .info
default: return .debug
// `debug` log level doesn't show up in Console.app when not building a Debug configuration
default: return isLoggingAccessible ? .info : .debug
}
}()

let braveCoreLogger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "brave-core")
if AppConstants.buildChannel.isPublic {
braveCoreLogger.log(level: level, "\(message, privacy: .private)")
} else {
if isLoggingAccessible {
braveCoreLogger.log(level: level, "\(message, privacy: .public)")
} else {
braveCoreLogger.log(level: level, "\(message, privacy: .private)")
}

return true
}

// Initialize BraveCore Switches
var switches: [BraveCoreSwitch] = []
if !AppConstants.buildChannel.isPublic {
// Check prefs for additional switches
let activeSwitches = Set(Preferences.BraveCore.activeSwitches.value)
let switchValues = Preferences.BraveCore.switchValues.value
for activeSwitch in activeSwitches {
let key = BraveCoreSwitchKey(rawValue: activeSwitch)
if key.isValueless {
switches.append(.init(key: key))
} else if let value = switchValues[activeSwitch], !value.isEmpty {
switches.append(.init(key: key, value: value))
}
// Check prefs for additional switches
let activeSwitches = Set(Preferences.BraveCore.activeSwitches.value)
let switchValues = Preferences.BraveCore.switchValues.value
for activeSwitch in activeSwitches {
let key = BraveCoreSwitchKey(rawValue: activeSwitch)
if key.isValueless {
switches.append(.init(key: key))
} else if let value = switchValues[activeSwitch], !value.isEmpty {
switches.append(.init(key: key, value: value))
}
}
switches.append(.init(key: .rewardsFlags, value: BraveRewards.Configuration.current().flags))
Expand Down
4 changes: 2 additions & 2 deletions ios/brave-ios/App/iOS/Delegates/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
Preferences.General.isFirstLaunch.value
}

PrivacyReportsManager.scheduleNotification(debugMode: !AppConstants.buildChannel.isPublic)
PrivacyReportsManager.scheduleNotification(debugMode: !AppConstants.isOfficialBuild)
PrivacyReportsManager.consolidateData()
PrivacyReportsManager.scheduleProcessingBlockedRequests(
isPrivateBrowsing: browserViewController.privateBrowsingManager.isPrivateBrowsing
Expand Down Expand Up @@ -536,7 +536,7 @@ extension SceneDelegate {
// Don't track crashes if we're building the development environment due to the fact that terminating/stopping
// the simulator via Xcode will count as a "crash" and lead to restore popups in the subsequent launch
let crashedLastSession =
!Preferences.AppState.backgroundedCleanly.value && AppConstants.buildChannel != .debug
!Preferences.AppState.backgroundedCleanly.value && AppConstants.isOfficialBuild

// Store the scene's activities
let windowId: UUID
Expand Down
8 changes: 6 additions & 2 deletions ios/brave-ios/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ var package = Package(
),
.target(
name: "BraveShared",
dependencies: ["BraveCore", "Shared"],
dependencies: ["BraveCore", "Shared", "Preferences"],
plugins: ["LoggerPlugin"]
),
.target(
Expand Down Expand Up @@ -577,7 +577,11 @@ if isNativeTalkEnabled {
)
package.products.append(.library(name: "BraveTalk", targets: ["BraveTalk"]))
package.targets.append(contentsOf: [
.target(name: "BraveTalk", dependencies: ["Shared", "JitsiMeet"], plugins: ["LoggerPlugin"]),
.target(
name: "BraveTalk",
dependencies: ["Shared", "Preferences", "JitsiMeet"],
plugins: ["LoggerPlugin"]
),
.testTarget(name: "BraveTalkTests", dependencies: ["BraveTalk", "Shared"]),
])
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class RewardsNotification: NSObject, BraveNotification {
guard let adView = view as? AdView else { return .automatic() }

var dismissTimeInterval: TimeInterval = 30
if !AppConstants.buildChannel.isPublic,
if !AppConstants.isOfficialBuild,
let override = Preferences.Rewards.adsDurationOverride.value, override > 0
{
dismissTimeInterval = TimeInterval(override)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,6 @@ class BraveRewardsViewController: UIViewController, PopoverContentComponent {
action: #selector(rewardsToggleValueChanged),
for: .valueChanged
)
if !AppConstants.buildChannel.isPublic {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tappedHostLabel(_:)))
rewardsView.publisherView.hostLabel.isUserInteractionEnabled = true
rewardsView.publisherView.hostLabel.addGestureRecognizer(tapGesture)
}
}

// MARK: - Actions
Expand Down Expand Up @@ -199,21 +194,4 @@ class BraveRewardsViewController: UIViewController, PopoverContentComponent {
@objc private func tappedUnverifiedPubLearnMore() {
actionHandler?(.unverifiedPublisherLearnMoreTapped)
}

// MARK: - Debug Actions

@objc private func tappedHostLabel(_ gesture: UITapGestureRecognizer) {
if gesture.state != .ended { return }
guard let publisher = publisher else { return }
rewards.rewardsAPI?.refreshPublisher(withId: publisher.id) { [weak self] status in
guard let self = self else { return }
let copy = publisher.copy() as! BraveCore.BraveRewards.PublisherInfo
copy.status = status
self.publisher = copy

let alert = UIAlertController(title: nil, message: "Refreshed", preferredStyle: .alert)
alert.addAction(.init(title: "OK", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ extension BrowserViewController {
return
}

let trackerCountThresholdForOnboarding = AppConstants.buildChannel.isPublic ? 250 : 20
let trackerCountThresholdForOnboarding = AppConstants.isOfficialBuild ? 250 : 20
let trackerAdsTotal =
BraveGlobalShieldStats.shared.adblock + BraveGlobalShieldStats.shared.trackingProtection

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1105,7 +1105,7 @@ public class BrowserViewController: UIViewController {
$0.body = Strings.DefaultBrowserCallout.notificationBody
}

let timeToShow = AppConstants.buildChannel.isPublic ? 2.hours : 2.minutes
let timeToShow = AppConstants.isOfficialBuild ? 2.hours : 2.minutes
let timeTrigger = UNTimeIntervalNotificationTrigger(
timeInterval: timeToShow,
repeats: false
Expand Down Expand Up @@ -3560,7 +3560,7 @@ extension BrowserViewController: PreferencesObserver {
PrivacyReportsManager.scheduleProcessingBlockedRequests(
isPrivateBrowsing: privateBrowsingManager.isPrivateBrowsing
)
PrivacyReportsManager.scheduleNotification(debugMode: !AppConstants.buildChannel.isPublic)
PrivacyReportsManager.scheduleNotification(debugMode: !AppConstants.isOfficialBuild)
case Preferences.PrivacyReports.captureVPNAlerts.key:
PrivacyReportsManager.scheduleVPNAlertsTask()
case Preferences.Wallet.defaultEthWallet.key:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,8 @@ class NewTabPageViewController: UIViewController {
action: #selector(tappedBraveNewsSettings),
for: .touchUpInside
)
if !AppConstants.buildChannel.isPublic {
if !AppConstants.isOfficialBuild {
// Add a shortcut only available in local builds
feedOverlayView.headerView.settingsButton.addGestureRecognizer(
UILongPressGestureRecognizer(
target: self,
Expand Down Expand Up @@ -1005,7 +1006,7 @@ class NewTabPageViewController: UIViewController {

@objc private func longPressedBraveNewsSettingsButton() {
assert(
!AppConstants.buildChannel.isPublic,
!AppConstants.isOfficialBuild,
"Debug settings are not accessible on public builds"
)
let settings = BraveNewsDebugSettingsView(dataSource: feedDataSource) { [weak self] in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ class NTPDefaultBrowserCalloutProvider: NSObject, NTPObservableSectionProvider {
let defaultBrowserDisplayCriteria =
!Preferences.General.defaultBrowserCalloutDismissed.value
&& !Preferences.Onboarding.basicOnboardingDefaultBrowserSelected.value
&& AppConstants.buildChannel == .release

guard let appRetentionLaunchDate = Preferences.DAU.appRetentionLaunchDate.value else {
return defaultBrowserDisplayCriteria
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ extension PrivacyReportsView {

DispatchQueue.main.async {
Preferences.PrivacyReports.shouldShowNotificationPermissionCallout.value = false
PrivacyReportsManager.scheduleNotification(debugMode: !AppConstants.buildChannel.isPublic)
PrivacyReportsManager.scheduleNotification(debugMode: !AppConstants.isOfficialBuild)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public struct PrivacyReportsManager {
public static func scheduleProcessingBlockedRequests(isPrivateBrowsing: Bool) {
saveBlockedResourcesTimer?.invalidate()

let timeInterval = AppConstants.buildChannel.isPublic ? 60.0 : 10.0
let timeInterval = AppConstants.isOfficialBuild ? 60.0 : 10.0

saveBlockedResourcesTimer = Timer.scheduledTimer(withTimeInterval: timeInterval, repeats: true)
{ _ in
Expand All @@ -51,7 +51,7 @@ public struct PrivacyReportsManager {

// Because fetching VPN alerts involves making a url request,
// the time interval to fetch them is longer than the local on-device blocked request processing.
let timeInterval = AppConstants.buildChannel.isPublic ? 5.minutes : 1.minutes
let timeInterval = AppConstants.isOfficialBuild ? 5.minutes : 1.minutes
vpnAlertsTimer = Timer.scheduledTimer(withTimeInterval: timeInterval, repeats: true) { _ in
if Preferences.PrivacyReports.captureVPNAlerts.value {
BraveVPN.processVPNAlerts()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class SearchSuggestionDataSource {

let rightNow = Date()
let nextShowDate = braveSearchPromotionLaunchDate.addingTimeInterval(
AppConstants.buildChannel.isPublic
AppConstants.isOfficialBuild
? maxPeriodBraveSearchPromotion.days : maxPeriodBraveSearchPromotion.minutes
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1259,9 +1259,7 @@ class TabManager: NSObject {
/// Function used to auto delete outdated Recently Closed Tabs
func deleteOutdatedRecentlyClosed() {
// The time interval to remove Recently Closed 3 days
let autoRemoveInterval = AppConstants.buildChannel.isPublic ? 30.minutes : 3.days

RecentlyClosed.deleteAll(olderThan: autoRemoveInterval)
RecentlyClosed.deleteAll(olderThan: 3.days)
}

/// An internal function to create a RecentlyClosed item from a tab
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,11 @@ extension Preferences {

/// Return time interval when to remove old tabs, or nil if no tabs should be removed.
public var timeInterval: TimeInterval? {
let isPublic = AppConstants.buildChannel.isPublic
switch self {
case .manually: return nil
case .oneDay: return isPublic ? 1.days : 5.minutes
case .oneWeek: return isPublic ? 7.days : 10.minutes
case .oneMonth: return isPublic ? 30.days : 1.hours
case .oneDay: return 1.days
case .oneWeek: return 7.days
case .oneMonth: return 30.days
}
}
}
Expand Down Expand Up @@ -287,7 +286,7 @@ extension Preferences {
)
}

final public class Debug {
final public class AdblockDebug {
/// When general blocklists were last time updated on the device.
static let lastGeneralAdblockUpdate = Option<Date?>(
key: "last-general-adblock-update",
Expand Down
Loading