Skip to content

Commit

Permalink
Fix #6421: debug setting to change FxA/sync servers (#6426)
Browse files Browse the repository at this point in the history
  • Loading branch information
garvankeeley committed Apr 20, 2020
1 parent 62439d8 commit 0f1624f
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 292 deletions.
250 changes: 62 additions & 188 deletions Client/Frontend/Settings/AdvancedAccountSettingViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,188 +8,94 @@ import SnapKit
import FxA
import Account

fileprivate class CustomFxAContentServerEnableSetting: BoolSetting {
init(prefs: Prefs, settingDidChange: ((Bool?) -> Void)? = nil) {
super.init(
prefs: prefs, prefKey: PrefsKeys.KeyUseCustomFxAContentServer, defaultValue: false,
attributedTitleText: NSAttributedString(string: Strings.SettingsAdvancedAccountUseCustomFxAContentServerURITitle),
settingDidChange: settingDidChange
)
}
}

fileprivate class CustomSyncTokenServerEnableSetting: BoolSetting {
init(prefs: Prefs, settingDidChange: ((Bool?) -> Void)? = nil) {
super.init(
prefs: prefs, prefKey: PrefsKeys.KeyUseCustomSyncTokenServerOverride, defaultValue: false,
attributedTitleText: NSAttributedString(string: Strings.SettingsAdvancedAccountUseCustomSyncTokenServerTitle),
settingDidChange: settingDidChange
)
}
}

fileprivate class CustomURLSetting: WebPageSetting {
override init(prefs: Prefs, prefKey: String, defaultValue: String? = nil, placeholder: String, accessibilityIdentifier: String, isChecked: @escaping () -> Bool = { return false }, settingDidChange: ((String?) -> Void)? = nil) {
super.init(prefs: prefs,
prefKey: prefKey,
defaultValue: defaultValue,
placeholder: placeholder,
accessibilityIdentifier: accessibilityIdentifier,
settingDidChange: settingDidChange)
textField.clearButtonMode = .always
}
}


class AdvancedAccountSettingViewController: SettingsTableViewController {
fileprivate let SectionHeaderIdentifier = "SectionHeaderIdentifier"

fileprivate var customAutoconfigURI: String?
fileprivate var customFxAContentURI: String?
fileprivate var customSyncTokenServerURI: String?

override func viewDidLoad() {
super.viewDidLoad()
title = Strings.SettingsAdvancedAccountTitle
self.customAutoconfigURI = self.profile.prefs.stringForKey(PrefsKeys.KeyCustomSyncWeb)
self.customFxAContentURI = self.profile.prefs.stringForKey(PrefsKeys.KeyCustomFxAContentServer)
self.customSyncTokenServerURI = self.profile.prefs.stringForKey(PrefsKeys.KeyCustomSyncTokenServerOverride)
}

func clearCustomAutoconfigPrefs() {
self.profile.prefs.setBool(false, forKey: PrefsKeys.KeyUseCustomAccountAutoconfig)
self.profile.prefs.setString("", forKey: PrefsKeys.KeyCustomSyncToken)
self.profile.prefs.setString("", forKey: PrefsKeys.KeyCustomSyncProfile)
self.profile.prefs.setString("", forKey: PrefsKeys.KeyCustomSyncOauth)
self.profile.prefs.setString("", forKey: PrefsKeys.KeyCustomSyncAuth)
self.profile.prefs.setString("", forKey: PrefsKeys.KeyCustomSyncWeb)

// To help prevent the account being in a strange state, we force it to
// log out when user clears their custom server preferences.
self.profile.removeAccount()
}

func setCustomAutoconfigPrefs() {
guard let customAutoconfigURIString = self.customAutoconfigURI, let customAutoconfigURI = URL(string: customAutoconfigURIString), customAutoconfigURI.schemeIsValid, customAutoconfigURI.host != nil else {
// If the user attempts to set a nil url, clear all the custom service perferences
// and use default FxA servers.
self.displayNoAutoconfigSetAlert()
return
}

// FxA stores its server configuation under a well-known path. This attempts to download the configuration
// and save it into the users preferences.
let syncConfigureString = customAutoconfigURIString + "/.well-known/fxa-client-configuration"
guard let syncConfigureURL = URL(string: syncConfigureString) else {
return
}

URLSession.shared.dataTask(with: syncConfigureURL, completionHandler: {(data, response, error) in
guard error == nil,
let data = data,
let json = (try? JSONSerialization.jsonObject(with: data, options: .allowFragments)) as? [String: Any],
let customSyncToken = json["sync_tokenserver_base_url"] as? String,
let customSyncProfile = json["profile_server_base_url"] as? String,
let customSyncOauth = json["oauth_server_base_url"] as? String,
let customSyncAuth = json["auth_server_base_url"] as? String else {

// Something went wrong while downloading or parsing the configuration.
self.displayAutoconfigErrorAlert()
return
}

self.profile.prefs.setBool(true, forKey: PrefsKeys.KeyUseCustomAccountAutoconfig)
self.profile.prefs.setString(customSyncToken, forKey: PrefsKeys.KeyCustomSyncToken)
self.profile.prefs.setString(customSyncProfile, forKey: PrefsKeys.KeyCustomSyncProfile)
self.profile.prefs.setString(customSyncOauth, forKey: PrefsKeys.KeyCustomSyncOauth)
self.profile.prefs.setString(customSyncAuth, forKey: PrefsKeys.KeyCustomSyncAuth)
self.profile.prefs.setString(customAutoconfigURI.absoluteString, forKey: PrefsKeys.KeyCustomSyncWeb)
self.profile.removeAccount()
self.displaySuccessAlert()
}).resume()
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
RustFirefoxAccounts.reconfig()
}

func clearCustomSyncTokenServerPrefs() {
self.profile.prefs.setBool(false, forKey: PrefsKeys.KeyUseCustomSyncTokenServerOverride)
self.profile.prefs.setString("", forKey: PrefsKeys.KeyCustomSyncTokenServerOverride)
}

func setCustomSyncTokenServerPrefs() {
guard let customSyncTokenServerURIString = self.customSyncTokenServerURI, let customSyncTokenServerURI = URL(string: customSyncTokenServerURIString), customSyncTokenServerURI.schemeIsValid, customSyncTokenServerURI.host != nil else {
// If the user attempts to set a nil url, clear all the custom service perferences
// and use default FxA servers.
self.displayNoTokenServerSetAlert()
return
}

self.profile.prefs.setBool(true, forKey: PrefsKeys.KeyUseCustomSyncTokenServerOverride)
self.profile.prefs.setString(customSyncTokenServerURI.absoluteString, forKey: PrefsKeys.KeyCustomSyncTokenServerOverride)
self.displaySuccessAlert()
}

func displaySuccessAlert() {
let alertController = UIAlertController(title: "", message: Strings.SettingsAdvancedAccountUrlUpdatedAlertMessage, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: Strings.OKString, style: .default, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true)
}

func displayAutoconfigErrorAlert() {
self.profile.prefs.setBool(false, forKey: PrefsKeys.KeyUseCustomAccountAutoconfig)
DispatchQueue.main.async {
self.tableView.reloadRows(at: [IndexPath(row: 0, section: 0)], with: .automatic)
}
let alertController = UIAlertController(title: Strings.SettingsAdvancedAccountUrlErrorAlertTitle, message: Strings.SettingsAdvancedAccountUrlErrorAlertMessage, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: Strings.OKString, style: .default, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true)
}
override func generateSettings() -> [SettingSection] {
let prefs = profile.prefs

func displayNoAutoconfigSetAlert() {
self.profile.prefs.setBool(false, forKey: PrefsKeys.KeyUseCustomAccountAutoconfig)
DispatchQueue.main.async {
self.tableView.reloadRows(at: [IndexPath(row: 0, section: 0)], with: .automatic)
let useStage = BoolSetting(prefs: prefs, prefKey: PrefsKeys.UseStageServer, defaultValue: false, attributedTitleText: NSAttributedString(string: NSLocalizedString("Use stage servers", comment: "Debug option"), attributes: [NSAttributedString.Key.foregroundColor: UIColor.theme.tableView.rowText]))
{ isOn in
self.settings = self.generateSettings()
self.tableView.reloadData()
}
let alertController = UIAlertController(title: Strings.SettingsAdvancedAccountUrlErrorAlertTitle, message: Strings.SettingsAdvancedAccountEmptyAutoconfigURIErrorAlertMessage, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: Strings.OKString, style: .default, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true)
}

func displayNoTokenServerSetAlert() {
self.profile.prefs.setBool(false, forKey: PrefsKeys.KeyUseCustomSyncTokenServerOverride)
DispatchQueue.main.async {
self.tableView.reloadRows(at: [IndexPath(row: 0, section: 2)], with: .automatic)
}
let alertController = UIAlertController(title: Strings.SettingsAdvancedAccountUrlErrorAlertTitle, message: Strings.SettingsAdvancedAccountEmptyTokenServerURIErrorAlertMessage, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: Strings.OKString, style: .default, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true)
}
let customFxA = CustomURLSetting(prefs: prefs,
prefKey: PrefsKeys.KeyCustomFxAContentServer,
placeholder: Strings.SettingsAdvancedAccountCustomFxAContentServerURI,
accessibilityIdentifier: "CustomFxAContentServer")

override func generateSettings() -> [SettingSection] {
let prefs = profile.prefs
let customAutoconfigURISetting = CustomURLSetting(prefs: prefs,
prefKey: PrefsKeys.KeyCustomSyncWeb,
placeholder: Strings.SettingsAdvancedAccountCustomAutoconfigURIPlaceholder,
accessibilityIdentifier: "CustomAutoconfigURISetting",
settingDidChange: { fieldText in
self.customAutoconfigURI = fieldText
if let customAutoconfigURI = self.customAutoconfigURI, customAutoconfigURI.isEmpty {
self.clearCustomAutoconfigPrefs()
return
}
})
let customSyncTokenServerURISetting = CustomURLSetting(prefs: prefs,
prefKey: PrefsKeys.KeyCustomSyncTokenServerOverride,
placeholder: Strings.SettingsAdvancedAccountCustomSyncTokenServerURIPlaceholder,
accessibilityIdentifier: "CustomSyncTokenServerURISetting",
settingDidChange: { fieldText in
self.customSyncTokenServerURI = fieldText
if let customSyncTokenServerURI = self.customSyncTokenServerURI, customSyncTokenServerURI.isEmpty {
self.clearCustomSyncTokenServerPrefs()
return
}
})
prefKey: PrefsKeys.KeyCustomSyncTokenServerOverride,
placeholder: Strings.SettingsAdvancedAccountCustomSyncTokenServerURI,
accessibilityIdentifier: "CustomSyncTokenServerURISetting")

let autoconfigSettings = [
CustomAutoconfigEnableSetting(
prefs: prefs,
settingDidChange: { result in
if result == true {
// Reload the table data to ensure that the updated value is set
self.tableView?.reloadData()
self.setCustomAutoconfigPrefs()
}
}),
customAutoconfigURISetting
CustomFxAContentServerEnableSetting(prefs: prefs) { isOn in
self.settings = self.generateSettings()
self.tableView.reloadData()
},
customFxA
]

let tokenServerSettings = [
CustomSyncTokenServerEnableSetting(
prefs: prefs,
settingDidChange: { result in
if result == true {
// Reload the table data to ensure that the updated value is set
self.tableView?.reloadData()
self.setCustomSyncTokenServerPrefs()
}
}),
CustomSyncTokenServerEnableSetting(prefs: prefs),
customSyncTokenServerURISetting
]

let settings: [SettingSection] = [
SettingSection(title: nil, children: autoconfigSettings),
SettingSection(title: NSAttributedString(string: Strings.SettingsAdvancedAccountAutoconfigSectionFooter), children: []),
SettingSection(title: nil, children: tokenServerSettings),
SettingSection(title: NSAttributedString(string: Strings.SettingsAdvancedAccountTokenServerSectionFooter), children: [])
]
var settings: [SettingSection] = [SettingSection(title:nil, children: [useStage])]

if !(prefs.boolForKey(PrefsKeys.UseStageServer) ?? false) {
settings.append(SettingSection(title: nil, children: autoconfigSettings))
settings.append(SettingSection(title: nil, children: tokenServerSettings))
}
return settings
}

Expand All @@ -208,35 +114,3 @@ class AdvancedAccountSettingViewController: SettingsTableViewController {
return headerView
}
}

class CustomAutoconfigEnableSetting: BoolSetting {
init(prefs: Prefs, settingDidChange: ((Bool?) -> Void)? = nil) {
super.init(
prefs: prefs, prefKey: PrefsKeys.KeyUseCustomAccountAutoconfig, defaultValue: false,
attributedTitleText: NSAttributedString(string: Strings.SettingsAdvancedAccountUseCustomAccountsServiceTitle),
settingDidChange: settingDidChange
)
}
}

class CustomSyncTokenServerEnableSetting: BoolSetting {
init(prefs: Prefs, settingDidChange: ((Bool?) -> Void)? = nil) {
super.init(
prefs: prefs, prefKey: PrefsKeys.KeyUseCustomSyncTokenServerOverride, defaultValue: false,
attributedTitleText: NSAttributedString(string: Strings.SettingsAdvancedAccountUseCustomSyncTokenServerTitle),
settingDidChange: settingDidChange
)
}
}

class CustomURLSetting: WebPageSetting {
override init(prefs: Prefs, prefKey: String, defaultValue: String? = nil, placeholder: String, accessibilityIdentifier: String, isChecked: @escaping () -> Bool = { return false }, settingDidChange: ((String?) -> Void)? = nil) {
super.init(prefs: prefs,
prefKey: prefKey,
defaultValue: defaultValue,
placeholder: placeholder,
accessibilityIdentifier: accessibilityIdentifier,
settingDidChange: settingDidChange)
textField.clearButtonMode = .always
}
}
48 changes: 12 additions & 36 deletions Client/Frontend/Settings/AppSettingsOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -465,10 +465,21 @@ class SlowTheDatabase: HiddenSetting {
}
}

class ForgetSyncAuthStateDebugSetting: HiddenSetting {
override var title: NSAttributedString? {
return NSAttributedString(string: NSLocalizedString("Debug: forget Sync auth state", comment: "Debug option"), attributes: [NSAttributedString.Key.foregroundColor: UIColor.theme.tableView.rowText])
}

override func onClick(_ navigationController: UINavigationController?) {
settings.profile.rustFxA.syncAuthState.invalidate()
settings.tableView.reloadData()
}
}

class SentryIDSetting: HiddenSetting {
let deviceAppHash = UserDefaults(suiteName: AppInfo.sharedContainerIdentifier)?.string(forKey: "SentryDeviceAppHash") ?? "0000000000000000000000000000000000000000"
override var title: NSAttributedString? {
return NSAttributedString(string: "Debug: \(deviceAppHash)", attributes: [NSAttributedString.Key.foregroundColor: UIColor.theme.tableView.rowText, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 10)])
return NSAttributedString(string: "Sentry ID: \(deviceAppHash)", attributes: [NSAttributedString.Key.foregroundColor: UIColor.theme.tableView.rowText, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 10)])
}

override func onClick(_ navigationController: UINavigationController?) {
Expand Down Expand Up @@ -846,41 +857,6 @@ class ChinaSyncServiceSetting: WithoutAccountSetting {
}
}

class StageSyncServiceDebugSetting: WithoutAccountSetting {
override var accessoryType: UITableViewCell.AccessoryType { return .none }
var prefs: Prefs { return settings.profile.prefs }

var prefKey: String = "useStageSyncService"

override var accessibilityIdentifier: String? { return "DebugStageSync" }

override var hidden: Bool {
if !ShowDebugSettings {
return true
}
return false
}

override var title: NSAttributedString? {
return NSAttributedString(string: NSLocalizedString("Debug: use stage servers", comment: "Debug option"), attributes: [NSAttributedString.Key.foregroundColor: UIColor.theme.tableView.rowText])
}

override func onConfigureCell(_ cell: UITableViewCell) {
super.onConfigureCell(cell)
let control = UISwitchThemed()
control.onTintColor = UIColor.theme.tableView.controlTint
control.addTarget(self, action: #selector(switchValueChanged), for: .valueChanged)
control.isOn = prefs.boolForKey(prefKey) ?? false
cell.accessoryView = control
cell.selectionStyle = .none
}

@objc func switchValueChanged(_ toggle: UISwitch) {
prefs.setObject(toggle.isOn, forKey: prefKey)
settings.tableView.reloadData()
}
}

class NewTabPageSetting: Setting {
let profile: Profile

Expand Down
8 changes: 2 additions & 6 deletions Client/Frontend/Settings/AppSettingsTableViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,6 @@ class AppSettingsTableViewController: SettingsTableViewController {
var settings = [SettingSection]()

let privacyTitle = NSLocalizedString("Privacy", comment: "Privacy section title")
let accountDebugSettings = [
// Debug settings:
//ForgetSyncAuthStateDebugSetting(settings: self),
StageSyncServiceDebugSetting(settings: self),
]

let prefs = profile.prefs
var generalSettings: [Setting] = [
Expand Down Expand Up @@ -98,7 +93,7 @@ class AppSettingsTableViewController: SettingsTableViewController {
// With a Firefox Account:
AccountStatusSetting(settings: self),
SyncNowSetting(settings: self)
] + accountChinaSyncSetting + accountDebugSettings)]
] + accountChinaSyncSetting )]

settings += [ SettingSection(title: NSAttributedString(string: Strings.SettingsGeneralSectionTitle), children: generalSettings)]

Expand Down Expand Up @@ -139,6 +134,7 @@ class AppSettingsTableViewController: SettingsTableViewController {
DeleteExportedDataSetting(settings: self),
ForceCrashSetting(settings: self),
SlowTheDatabase(settings: self),
ForgetSyncAuthStateDebugSetting(settings: self),
SentryIDSetting(settings: self),
])]

Expand Down

0 comments on commit 0f1624f

Please sign in to comment.