Skip to content

Commit

Permalink
Merge rust-fxa branch to master (#6328)
Browse files Browse the repository at this point in the history
* First FxA Rust integrations steps (#6077)

* restore use of fxa flow type arg (+4 squashed commits)
Squashed commits:
[c3769e1b9] Push is working!!
[3ea28f833] hookup apns and disconnect account
[a217e9e77] hookup device constellation
[4e65ff129] initial hookup

* hooked up sending tabs using the device list

* Remove using optional RustFirefoxAccounts.shared

* Add stub key migration code

* Update syncUnlockInfo to use getAccessToken(scope: FxAOAuthScope.OldSync)

* RustFirefoxAccounts.shared: guard against re-entrancy

* update app services SHA

* Use NSLock instead of objc_sync_enter

* app-services v0.50.0

* patch cleanup

*  PlacesAPI.resetBookmarksMetadata() is gone, and there is a PlacesAPI.resetBookmarkSyncMetadata.

* update Cartfile.resolved for protobuf 1.8.0

* Remove use of getAccount(), except in the sync case as that is in-progress

* revert changes to Fennec xcscheme

* wip legacy sync

* Fix #6108: populate remote_devices table with new rust fxa component

* hooked up webchannel for fxa login

* Hookup account management. Hookup token migration

* handle push messages for connect and disconnect

* Migration of tokens on updating app

* Show caution icon when migration failed, clear it when sign in to sync is shown

* Hookup webchannel deleteAccount and changePassword. Hookup help viewer in FxAWebView

* Fix migration bug: push notification re-registration is required

* CWTS (#6124)

Co-authored-by: Garvan Keeley <[email protected]>

* Fix sync tabs not working, clients table not populated

* hookup device deleted push notification

* Remove force-unwraps in Profile sync code

* Fix account disconnect when app in foreground. Fix re-login not registering APNS.

* Hookup getTokenServerEndpointURL()

* disable broken tests

* Remove failing fxa push message test

* Use Firefox iOS client ID for FxA

* Set version to 23.1 for releasing a beta

* Handle fxaccounts:logout message.

* Add PushNotificationSetup.swift, and more FirefoxAccount removal

* Setup china server URL for FxA

* Fix #6201 - send to device from extension

* fix broken test

* Handle password change properly (#6205)

* Fix #6182: China sync servers using wrong URL (#6213)

* Fix #6211: app settings for sign-in was not loading the fxawebview (#6217)

* Fix #6212: CWTS options in webview need to be reflected in native settings (#6219)

* Fix #6212: CWTS options in webview need to be reflected in native settings

* remove for loop

* remove duplicate logout() calls

* Fix #6221 and #6229: page dismissed after changing password

* Fix #6207 - dismiss picker after send

* Fix displaying tab sent notification (was accidentally unhooked)

* Fix #6231 - Device picker not updating to latest list (#6238)

* Fix #6231 - Device picker not updating to latest list

* Avoid reloadData if the device list is unchanged

* Use new FxAConfig.china() syntax

* Remove FirefoxAccountSyncAuthState TODO for keychain storage (#6243)

* Remove FxAContentViewController, replaced by FxAWebView

* Add debugging info to push notification messages

* Update the appmenu UI when fxaccount is ready

* Add user profile caching for offline state

* a-s lib to 0.54.1

* fix test breakage

* getTokenServerEndpointURL() is now async

* Add comments to new rust fxa code, split app delegate up for clarity (#6280)

* Add comments to new rust fxa code

* Split up app delegate for push notification handling, and sync sent tab handling

* fix swift lint issues

* address nits

* disconnect was not deleting the cached user profile

Co-authored-by: Edouard Oger <[email protected]>
  • Loading branch information
garvankeeley and eoger authored Mar 30, 2020
1 parent 6cbbc75 commit 948bcf9
Show file tree
Hide file tree
Showing 50 changed files with 1,350 additions and 2,205 deletions.
123 changes: 3 additions & 120 deletions Account/FirefoxAccount.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ open class FirefoxAccount {

let stateCache: KeychainCacheState

open var syncAuthState: SyncAuthState! // We can't give a reference to self if this is a let.
// open var syncAuthState: SyncAuthState! // We can't give a reference to self if this is a let.

// To prevent advance() consumers racing, we maintain a shared advance() deferred (`advanceDeferred`). If an
// advance() is in progress, the shared deferred will be returned. (Multiple consumers can chain off a single
Expand Down Expand Up @@ -91,8 +91,8 @@ open class FirefoxAccount {
self.deviceName = deviceName

self.commandsClient = FxACommandsClient(account: self)
self.syncAuthState = FirefoxAccountSyncAuthState(account: self,
cache: KeychainCache.fromBranch("account.syncAuthState", withLabel: self.stateCache.label, factory: syncAuthStateCachefromJSON))
// self.syncAuthState = FirefoxAccountSyncAuthState(account: self,
// cache: KeychainCache.fromBranch("account.syncAuthState", withLabel: self.stateCache.label, factory: syncAuthStateCachefromJSON))
}

open class func from(_ configuration: FirefoxAccountConfiguration, andJSON data: JSON) -> FirefoxAccount? {
Expand Down Expand Up @@ -242,66 +242,6 @@ open class FirefoxAccount {
self.displayName = displayName
self.avatar = Avatar(url: avatar?.asURL)
}

enum ImageDownloadState {
case notStarted
case started
case failedCanRetry
case failedCanNotRetry
case succeededMalformed
case succeeded
}

open class Avatar {
open var image: UIImage?
public let url: URL?
var currentImageState: ImageDownloadState = .notStarted

init(url: URL?) {
self.image = UIImage(named: "placeholder-avatar")
self.url = url
self.updateAvatarImageState()
}

func updateAvatarImageState() {
switch currentImageState {
case .notStarted:
self.currentImageState = .started
self.downloadAvatar()
break
case .failedCanRetry:
self.downloadAvatar()
break
default:
break
}
}

func downloadAvatar() {
SDWebImageManager.shared.loadImage(with: url, options: [.continueInBackground, .lowPriority], progress: nil) { (image, _, error, _, success, _) in
if let error = error {
if (error as NSError).code == 404 || self.currentImageState == .failedCanRetry {
// Image is not found or failed to download a second time
self.currentImageState = .failedCanNotRetry
} else {
// This could have been a transient error, attempt to download the image only once more
self.currentImageState = .failedCanRetry
self.updateAvatarImageState()
}
return
}

if success == true && image == nil {
self.currentImageState = .succeededMalformed
return
}

self.image = image
self.currentImageState = .succeeded
NotificationCenter.default.post(name: .FirefoxAccountProfileChanged, object: self)
}
}
}
}

// Don't forget to call Profile.flushAccount() to persist this change!
Expand Down Expand Up @@ -348,29 +288,6 @@ open class FirefoxAccount {
}
}

open func syncUnlockInfo() -> Deferred<Maybe<SyncUnlockInfo>> {
guard let married = stateCache.value as? MarriedState else {
return deferMaybe(NotATokenStateError(state: stateCache.value))
}
let client = FxAClient10(configuration: configuration)
return client.oauthAuthorize(withSessionToken: married.sessionToken as NSData, scope: FxAOAuthScope.OldSync).bind({ result in
guard let oauthResponse = result.successValue else {
return deferMaybe(ScopedKeyError())
}

return self.oauthKeyID(for: FxAOAuthScope.OldSync).bind({ result in
guard let kid = result.successValue,
let kSync = married.kSync.base64urlSafeEncodedString else {
return deferMaybe(ScopedKeyError())
}

let accessToken = oauthResponse.accessToken
let tokenServerURL = self.configuration.sync15Configuration.tokenServerEndpointURL.absoluteString
return deferMaybe(SyncUnlockInfo(kid: kid, fxaAccessToken: accessToken, syncKey: kSync, tokenserverURL: tokenServerURL))
})
})
}

// Fetch the devices list from FxA then replace the current stored remote devices.
open func updateFxADevices(remoteDevices: RemoteDevices) -> Success {
guard let session = stateCache.value as? TokenState else {
Expand All @@ -382,44 +299,10 @@ open class FirefoxAccount {
}
}

open func oauthKeyID(for scope: String) -> Deferred<Maybe<String>> {
// Ensure we are in a "married" state before continuing.
guard let married = stateCache.value as? MarriedState else {
return deferMaybe(NotATokenStateError(state: stateCache.value))
}
// This method of forming a KeyID is currently only valid for 'oldsync'.
guard scope == FxAOAuthScope.OldSync else {
log.error("oauthKeyID(for scope:) is currently only valid for 'oldsync'.")
return deferMaybe(ScopedKeyError())
}
// If we have a cached copy of the KeyID in the Keychain, use it.
let kidKeychainKey = "FxAOAuthKeyID:\(scope)"
if let cachedOAuthKeyID = KeychainStore.shared.string(forKey: kidKeychainKey) {
return deferMaybe(cachedOAuthKeyID)
}
// Otherwise, request the scoped key data from the server.
let client = FxAClient10(configuration: configuration)
return client.scopedKeyData(married.sessionToken as NSData, scope: scope).bind { response in
guard let allScopedKeyData = response.successValue, let scopedKeyData = allScopedKeyData.find({ $0.scope == scope }), let kXCS = married.kXCS.hexDecodedData.base64urlSafeEncodedString else {
return deferMaybe(ScopedKeyError())
}
let kid = "\(scopedKeyData.keyRotationTimestamp)-\(kXCS)"

// Cache the KeyID in the Keychain for subsequent requests.
KeychainStore.shared.setString(kid, forKey: kidKeychainKey)

return deferMaybe(kid)
}
}

public class NotifyError: MaybeErrorType {
public var description = "The server could not notify the clients."
}

public class ScopedKeyError: MaybeErrorType {
public var description = "No key data found for scope."
}

@discardableResult open func notify(deviceIDs: [GUID], collectionsChanged collections: [String], reason: String) -> Success {
guard let session = stateCache.value as? TokenState else {
return deferMaybe(NotATokenStateError(state: stateCache.value))
Expand Down
2 changes: 1 addition & 1 deletion Account/FxALoginStateMachine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,6 @@ class FxALoginStateMachine {
}

fileprivate func notifyAccountVerified() {
NotificationCenter.default.post(name: .FirefoxAccountVerified, object: nil, userInfo: nil)
// NotificationCenter.default.post(name: .FirefoxAccountVerified, object: nil, userInfo: nil)
}
}
Loading

0 comments on commit 948bcf9

Please sign in to comment.