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

Commit

Permalink
Fix #3921: Use device authentication for browser lock feature
Browse files Browse the repository at this point in the history
  • Loading branch information
kylehickinson committed Jul 14, 2021
1 parent f4870ae commit 5b79189
Show file tree
Hide file tree
Showing 38 changed files with 627 additions and 1,180 deletions.
52 changes: 9 additions & 43 deletions BraveShared/BraveStrings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,6 @@ extension Strings {
bundle: .braveShared, value: "Oops! Something went wrong. Please try again.", comment: "")
}

// MARK:- BasePasscodeViewController.swift
extension Strings {
public static let passcodeConfirmMisMatchErrorText = NSLocalizedString("PasscodeConfirmMisMatchErrorText", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Passcodes didn’t match. Try again.", comment: "Error message displayed to user when their confirming passcode doesn't match the first code.")
public static let passcodeMatchOldErrorText = NSLocalizedString("PasscodeMatchOldErrorText", tableName: "BraveShared", bundle: Bundle.braveShared, value: "New passcode must be different than existing code.", comment: "Error message displayed when user tries to enter the same passcode as their existing code when changing it.")
}

// MARK:- SearchViewController.swift
extension Strings {
public static let searchSettingsButtonTitle = NSLocalizedString("SearchSettingsButtonTitle", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Search Settings", comment: "Label for search settings button.")
Expand Down Expand Up @@ -410,53 +404,23 @@ extension Strings {
public static let menuItemOpenAndFillTitle = NSLocalizedString("MenuItemOpenAndFillTitle", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Open & Fill", comment: "Open and Fill website text selection menu item")
}

// MARK:- AuthenticationManagerConstants.swift
// MARK: - Passcode / Browser Lock
extension Strings {
public static let authenticationPasscode = NSLocalizedString("AuthenticationPasscode", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Passcode For Logins", comment: "Label for the Passcode item in Settings")
public static let authenticationPasscode = NSLocalizedString("AuthenticationPasscode", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Passcode", comment: "Label for the Passcode item in Settings")

public static let authenticationTouchIDPasscodeSetting = NSLocalizedString("AuthenticationTouchIDPasscodeSetting", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Touch ID & Passcode", comment: "Label for the Touch ID/Passcode item in Settings")

public static let authenticationFaceIDPasscodeSetting = NSLocalizedString("AuthenticationFaceIDPasscodeSetting", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Face ID & Passcode", comment: "Label for the Face ID/Passcode item in Settings")

public static let authenticationRequirePasscode = NSLocalizedString("AuthenticationRequirePasscode", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Require Passcode", comment: "Text displayed in the 'Interval' section, followed by the current interval setting, e.g. 'Immediately'")

public static let authenticationEnterAPasscode = NSLocalizedString("AuthenticationEnterAPasscode", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Enter a passcode", comment: "Text displayed above the input field when entering a new passcode")

public static let authenticationEnterPasscodeTitle = NSLocalizedString("AuthenticationEnterPasscodeTitle", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Enter Passcode", comment: "Title of the dialog used to request the passcode")

public static let authenticationEnterPasscode = NSLocalizedString("AuthenticationEnterPasscode", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Enter passcode", comment: "Text displayed above the input field when changing the existing passcode")

public static let authenticationReenterPasscode = NSLocalizedString("AuthenticationReenterPasscode", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Re-enter passcode", comment: "Text displayed above the input field when confirming a passcode")

public static let authenticationSetPasscode = NSLocalizedString("AuthenticationSetPasscode", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Set Passcode", comment: "Title of the dialog used to set a passcode")

public static let authenticationTurnOffPasscode = NSLocalizedString("AuthenticationTurnOffPasscode", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Turn Passcode Off", comment: "Label used as a setting item to turn off passcode")

public static let authenticationTurnOnPasscode = NSLocalizedString("AuthenticationTurnOnPasscode", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Turn Passcode On", comment: "Label used as a setting item to turn on passcode")

public static let authenticationChangePasscode = NSLocalizedString("AuthenticationChangePasscode", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Change Passcode", comment: "Label used as a setting item and title of the following screen to change the current passcode")

public static let authenticationEnterNewPasscode = NSLocalizedString("AuthenticationEnterNewPasscode", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Enter a new passcode", comment: "Text displayed above the input field when changing the existing passcode")

public static let authenticationImmediately = NSLocalizedString("AuthenticationImmediately", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Immediately", comment: "Immediately' interval item for selecting when to require passcode")

public static let authenticationLoginsTouchReason = NSLocalizedString("AuthenticationLoginsTouchReason", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Use your fingerprint to access Logins now.", comment: "Touch ID prompt subtitle when accessing logins")

public static let authenticationRequirePasscodeTouchReason = NSLocalizedString("AuthenticationRequirePasscodeTouchReason", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Use your fingerprint to access configuring your required passcode interval.", comment: "Touch ID prompt subtitle when accessing the require passcode setting")

public static let authenticationDisableTouchReason = NSLocalizedString("AuthenticationDisableTouchReason", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Use your fingerprint to disable Touch ID.", comment: "Touch ID prompt subtitle when disabling Touch ID")

public static let authenticationWrongPasscodeError = NSLocalizedString("AuthenticationWrongPasscodeError", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Incorrect passcode. Try again.", comment: "Error message displayed when user enters incorrect passcode when trying to enter a protected section of the app")

public static let authenticationIncorrectAttemptsRemaining = NSLocalizedString("AuthenticationIncorrectAttemptsRemaining", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Incorrect passcode. Try again (Attempts remaining: %d).", comment: "Error message displayed when user enters incorrect passcode when trying to enter a protected section of the app with attempts remaining")
public static let authenticationLoginsTouchReason = NSLocalizedString("AuthenticationLoginsTouchReason", tableName: "BraveShared", bundle: Bundle.braveShared, value: "This authenticates your access to Brave", comment: "Touch ID or PIN entry prompt subtitle when accessing Brave with the Browser Lock feature enabled")

public static let authenticationMaximumAttemptsReached = NSLocalizedString("AuthenticationMaximumAttemptsReached", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Too many failed attempts.\n Please try again in %d minutes.", comment: "Error message displayed when user enters incorrect passcode and has reached the maximum number of attempts.")
public static let browserLockMigrationTitle = NSLocalizedString("browserLockMigrationTitle", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Open Brave with your Apple Face ID, Touch ID, or passcode", comment: "Title on the screen shown to the user when they are being migrated from the old Passcode feature to the new Browser Lock feature")

public static let authenticationMaximumAttemptsReachedOneMinute = NSLocalizedString("AuthenticationMaximumAttemptsReachedOneMinute", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Too many failed attempts.\n Please try again in 1 minute.", comment: "Error message displayed when user enters incorrect passcode and has reached the maximum number of attempts.")
public static let browserLockMigrationSubtitle = NSLocalizedString("browserLockMigrationSubtitle", tableName: "BraveShared", bundle: Bundle.braveShared, value: "We’ve simplified Brave Passcodes. You can now access Brave with the same ID or passcode you use on your phone.", comment: "Subtitle on the screen shown to the user when they are being migrated from the old Passcode feature to the new Browser Lock feature")

public static let authenticationMaximumAttemptsReachedNoTime = NSLocalizedString("AuthenticationMaximumAttemptsReachedNoTime", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Maximum attempts reached. Please try again later.", comment: "Error message displayed when user enters incorrect passcode and has reached the maximum number of attempts.")
public static let browserLockMigrationNoPasscodeSetup = NSLocalizedString("browserLockMigrationNoPasscodeSetup", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Haven't set an ID or passcode? Open Settings, then tap \"%@\"", comment: "Displayed to the user when they don't have a passcode set on their phone, therefore cannot use the Browser Lock feature. \"%@\" will be filled with either \"Touch ID & Passcode\" or \"Face ID & Passcode\"")

public static let authenticationTouchForKeyboard = NSLocalizedString("AuthenticationTouchForKeyboard", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Tap to bring up the keyboard accessibility", comment: "When the user taps on the passcode pane, the touch gesture recognizer will bring up the keyboard back on the screen when hidden on iPad.")
public static let browserLockMigrationContinueButtonTitle = NSLocalizedString("browserLockMigrationContinueButtonTitle", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Continue", comment: "A button title for the action to move to the next step of the browser lock migration process.")
}

// MARK:- Settings.
Expand Down Expand Up @@ -621,6 +585,8 @@ extension Strings {
public static let confirm = NSLocalizedString("Confirm", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Confirm", comment: "")
public static let privacy = NSLocalizedString("Privacy", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Privacy", comment: "Settings privacy section title")
public static let security = NSLocalizedString("Security", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Security", comment: "Settings security section title")
public static let browserLock = NSLocalizedString("BrowserLock", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Browser Lock", comment: "Setting to enable the browser lock privacy feature")
public static let browserLockDescription = NSLocalizedString("BrowserLockDescription", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Unlock Brave with Touch ID, Face ID or system passcode.", comment: "")
public static let saveLogins = NSLocalizedString("SaveLogins", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Save Logins", comment: "Setting to enable the built-in password manager")
public static let showBookmarkButtonInTopToolbar = NSLocalizedString("ShowBookmarkButtonInTopToolbar", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Show Bookmarks Shortcut", comment: "Setting to show a bookmark button on the top level menu that triggers a panel of the user's bookmarks.")
public static let alwaysRequestDesktopSite = NSLocalizedString("AlwaysRequestDesktopSite", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Always Request Desktop Site", comment: "Setting to always request the desktop version of a website.")
Expand Down
4 changes: 2 additions & 2 deletions BraveUI/Buttons/ActionButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import UIKit
import BraveShared

open class ActionButton: Button {
open class ActionButton: BraveButton {

override public init(frame: CGRect) {
super.init(frame: frame)
Expand Down Expand Up @@ -35,7 +35,7 @@ open class ActionButton: Button {
}
}

open class FilledActionButton: Button {
open class FilledActionButton: BraveButton {
override public init(frame: CGRect) {
super.init(frame: frame)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import SnapKit
/// - Flipping the image placement
/// - Applying a larger hit area without adjusting the bounds
/// - Sizing correctly when adding setting `titleEdgeInsets` and `imageEdgeInsets`
open class Button: UIButton {
open class BraveButton: UIButton {

// MARK: - Activity

Expand Down
40 changes: 31 additions & 9 deletions BraveUI/Design System/Colors/Gradients.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,41 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import UIKit
import struct SwiftUI.Angle
import SwiftUI

extension Gradient {
init(braveGradient gradient: BraveGradient) {
self.init(
stops: gradient.stops.map { stop in
.init(color: Color(stop.color), location: CGFloat(stop.position))
}
)
}
}

extension LinearGradient {
/// Create a SwiftUI LinearGradient from a Brave defined Gradient
public init(braveGradient gradient: BraveGradient) {
assert(gradient.type == .axial, "Attempting to create a LinearGradient with a non-linear Brave defined gradient")
self.init(
gradient: Gradient(braveGradient: gradient),
startPoint: .init(x: gradient.startPoint.x, y: gradient.startPoint.y),
endPoint: .init(x: gradient.endPoint.x, y: gradient.endPoint.y)
)
}
}

public struct BraveGradient {
public struct Stop {
var color: UIColor
var position: Double
public var color: UIColor
public var position: Double
}
var type: CAGradientLayerType = .axial
var stops: [Stop]
var startPoint: CGPoint
var endPoint: CGPoint
public var type: CAGradientLayerType = .axial
public var stops: [Stop]
public var startPoint: CGPoint
public var endPoint: CGPoint

init(stops: [Stop], angle: Angle) {
public init(stops: [Stop], angle: Angle) {
let alpha = angle.radians
let startPoint = CGPoint(
x: 0.5 * sin(alpha) + 0.5,
Expand All @@ -28,7 +50,7 @@ public struct BraveGradient {
self.init(stops: stops, startPoint: startPoint, endPoint: endPoint)
}

init(stops: [Stop], startPoint: CGPoint, endPoint: CGPoint) {
public init(stops: [Stop], startPoint: CGPoint, endPoint: CGPoint) {
self.stops = stops
self.startPoint = startPoint
self.endPoint = endPoint
Expand Down
130 changes: 130 additions & 0 deletions BraveUI/Design System/Views/BraveButtonStyle.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// Copyright 2021 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

import SwiftUI

public struct BraveButtonSize {
public var font: Font
public var padding: EdgeInsets

public init(font: Font, padding: EdgeInsets) {
self.font = font
self.padding = padding
}

public static let small: Self = .init(
font: Font.caption.weight(.semibold),
padding: .init(top: 6, leading: 12, bottom: 6, trailing: 12)
)
public static let normal: Self = .init(
font: Font.callout.weight(.semibold),
padding: .init(top: 8, leading: 14, bottom: 8, trailing: 14)
)
public static let large: Self = .init(
font: Font.body.weight(.semibold),
padding: .init(top: 10, leading: 20, bottom: 10, trailing: 20)
)
}

public struct BraveFilledButtonStyle: ButtonStyle {
@Environment(\.isEnabled) private var isEnabled

public var size: BraveButtonSize

public init(size: BraveButtonSize) {
self.size = size
}

public func makeBody(configuration: Configuration) -> some View {
configuration.label
.opacity(configuration.isPressed ? 0.7 : 1.0)
.font(size.font)
.foregroundColor(.white)
.padding(size.padding)
.background(
Group {
if isEnabled {
Color(.braveBlurple).opacity(configuration.isPressed ? 0.7 : 1.0)
} else {
Color(.braveDisabled)
}
}
)
.clipShape(Capsule())
.contentShape(Capsule())
.animation(.linear(duration: 0.15), value: isEnabled)
}
}

public struct BraveOutlineButtonStyle: ButtonStyle {
@Environment(\.isEnabled) private var isEnabled

public var size: BraveButtonSize

public init(size: BraveButtonSize) {
self.size = size
}

public func makeBody(configuration: Configuration) -> some View {
configuration.label
.opacity(configuration.isPressed ? 0.7 : 1.0)
.font(size.font)
.foregroundColor(isEnabled ? Color(.braveLabel) : Color(.braveDisabled))
.padding(size.padding)
.background(
Group {
if isEnabled {
Color(.secondaryButtonTint).opacity(configuration.isPressed ? 0.7 : 1.0)
} else {
Color(.braveDisabled)
}
}
.clipShape(Capsule().inset(by: 0.5).stroke())
)
.clipShape(Capsule())
.contentShape(Capsule())
.animation(.linear(duration: 0.15), value: isEnabled)
}
}

struct BraveButtonStyle_Previews: PreviewProvider {
static let defaultSizes: [BraveButtonSize] = [
.small, .normal, .large
]

static var previews: some View {
Group {
HStack {
ForEach([false, true], id: \.self) { disabled in
VStack {
ForEach(defaultSizes.indices) { index in
Button(action: { }) {
Text("Button text")
}
.buttonStyle(BraveFilledButtonStyle(size: defaultSizes[index]))
.disabled(disabled)
}
}
.padding()
}
}
HStack {
ForEach([false, true], id: \.self) { disabled in
VStack {
ForEach(defaultSizes.indices) { index in
Button(action: { }) {
Text("Button text")
}
.buttonStyle(BraveOutlineButtonStyle(size: defaultSizes[index]))
.disabled(disabled)
}
}
.padding()
}
}
}
.previewLayout(.sizeThatFits)
}
}
Loading

0 comments on commit 5b79189

Please sign in to comment.