-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Remote Messaging Framework for macOS (#876)
Task/Issue URL: https://app.asana.com/0/72649045549333/1202913520695928/f Description: This change adds support for RMF on macOS. * Remaining RMF functionality previously present in iOS codebase was moved to BSK (most importantly RemoteMessagingProcessing protocol). * remoteMessaging feature flag was added. * RemoteMessagingConfigMatcherProviding protocol was added – it's implemented by client apps to create and return the config matcher filled with current values of matching attributes. * Support for platform-specific user attribute matchers was added. CommonUserAttributeMatcher was added to handle attributes that are the supported on both iOS and macOS. Mobile and Desktop user attribute matcher structs were added to support platform-specific attributes (currently it's only isWidgetInstalled for iOS). * RemoteMessagingRequest was replaced with RemoteMessagingConfigFetcher that uses Configuration Store and supports Etags. * All RMF tests (and mocks) were moved out of BrowserServicesKit(Tests) into RemoteMessagingTestsUtils and RemoteMessagingTests (that also mandated creating EmailTestsUtils). * RemoteMessagingStore was updated to keep a reference to the database and create contexts on demand, to ensure it always gets the freshest data from the persistent store.
- Loading branch information
Showing
49 changed files
with
1,947 additions
and
624 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
65 changes: 65 additions & 0 deletions
65
Sources/BrowserServicesKitTestsUtils/MockEmailManagerRequestDelegate.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// | ||
// MockEmailManagerRequestDelegate.swift | ||
// | ||
// Copyright © 2024 DuckDuckGo. All rights reserved. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// | ||
|
||
@testable import BrowserServicesKit | ||
import Foundation | ||
|
||
public class MockEmailManagerRequestDelegate: EmailManagerRequestDelegate { | ||
|
||
public init(didSendMockAliasRequest: @escaping () -> Void = {}) { | ||
self.didSendMockAliasRequest = didSendMockAliasRequest | ||
} | ||
|
||
public var activeTask: URLSessionTask? | ||
public var mockAliases: [String] = [] | ||
public var waitlistTimestamp: Int = 1 | ||
public var didSendMockAliasRequest: () -> Void | ||
|
||
// swiftlint:disable function_parameter_count | ||
public func emailManager(_ emailManager: EmailManager, requested url: URL, method: String, headers: [String: String], parameters: [String: String]?, httpBody: Data?, timeoutInterval: TimeInterval) async throws -> Data { | ||
switch url.absoluteString { | ||
case EmailUrls.Url.emailAlias: return try processMockAliasRequest().get() | ||
default: fatalError("\(#file): Unsupported URL passed to mock request delegate: \(url)") | ||
} | ||
} | ||
// swiftlint:enable function_parameter_count | ||
|
||
public var keychainAccessErrorAccessType: EmailKeychainAccessType? | ||
public var keychainAccessError: EmailKeychainAccessError? | ||
|
||
public func emailManagerKeychainAccessFailed(_ emailManager: EmailManager, | ||
accessType: EmailKeychainAccessType, | ||
error: EmailKeychainAccessError) { | ||
keychainAccessErrorAccessType = accessType | ||
keychainAccessError = error | ||
} | ||
|
||
private func processMockAliasRequest() -> Result<Data, Error> { | ||
didSendMockAliasRequest() | ||
|
||
if mockAliases.first != nil { | ||
let alias = mockAliases.removeFirst() | ||
let jsonString = "{\"address\":\"\(alias)\"}" | ||
let data = jsonString.data(using: .utf8)! | ||
return .success(data) | ||
} else { | ||
return .failure(AliasRequestError.noDataError) | ||
} | ||
} | ||
|
||
} |
90 changes: 90 additions & 0 deletions
90
Sources/BrowserServicesKitTestsUtils/MockEmailManagerStorage.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// | ||
// MockEmailManagerStorage.swift | ||
// | ||
// Copyright © 2024 DuckDuckGo. All rights reserved. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// | ||
|
||
import BrowserServicesKit | ||
import Foundation | ||
|
||
public class MockEmailManagerStorage: EmailManagerStorage { | ||
|
||
public var mockError: EmailKeychainAccessError? | ||
|
||
public var mockUsername: String? | ||
public var mockToken: String? | ||
public var mockAlias: String? | ||
public var mockCohort: String? | ||
public var mockLastUseDate: String? | ||
|
||
public var storeTokenCallback: ((String, String, String?) -> Void)? | ||
public var storeAliasCallback: ((String) -> Void)? | ||
public var storeLastUseDateCallback: ((String) -> Void)? | ||
public var deleteAliasCallback: (() -> Void)? | ||
public var deleteAuthenticationStateCallback: (() -> Void)? | ||
public var deleteWaitlistStateCallback: (() -> Void)? | ||
|
||
public init() {} | ||
|
||
public func getUsername() throws -> String? { | ||
if let mockError = mockError { throw mockError } | ||
return mockUsername | ||
} | ||
|
||
public func getToken() throws -> String? { | ||
if let mockError = mockError { throw mockError } | ||
return mockToken | ||
} | ||
|
||
public func getAlias() throws -> String? { | ||
if let mockError = mockError { throw mockError } | ||
return mockAlias | ||
} | ||
|
||
public func getCohort() throws -> String? { | ||
if let mockError = mockError { throw mockError } | ||
return mockCohort | ||
} | ||
|
||
public func getLastUseDate() throws -> String? { | ||
if let mockError = mockError { throw mockError } | ||
return mockLastUseDate | ||
} | ||
|
||
public func store(token: String, username: String, cohort: String?) throws { | ||
storeTokenCallback?(token, username, cohort) | ||
} | ||
|
||
public func store(alias: String) throws { | ||
storeAliasCallback?(alias) | ||
} | ||
|
||
public func store(lastUseDate: String) throws { | ||
storeLastUseDateCallback?(lastUseDate) | ||
} | ||
|
||
public func deleteAlias() { | ||
deleteAliasCallback?() | ||
} | ||
|
||
public func deleteAuthenticationState() { | ||
deleteAuthenticationStateCallback?() | ||
} | ||
|
||
public func deleteWaitlistState() { | ||
deleteWaitlistStateCallback?() | ||
} | ||
|
||
} |
36 changes: 36 additions & 0 deletions
36
Sources/BrowserServicesKitTestsUtils/MockStatisticsStore.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// | ||
// MockStatisticsStore.swift | ||
// | ||
// Copyright © 2024 DuckDuckGo. All rights reserved. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// | ||
|
||
import BrowserServicesKit | ||
import Foundation | ||
|
||
public class MockStatisticsStore: StatisticsStore { | ||
|
||
public init() {} | ||
|
||
public var installDate: Date? | ||
public var atb: String? | ||
public var searchRetentionAtb: String? | ||
public var appRetentionAtb: String? | ||
|
||
public var hasInstallStatistics: Bool { | ||
return atb != nil | ||
} | ||
|
||
public var variant: String? | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// | ||
// MockVariant.swift | ||
// | ||
// Copyright © 2024 DuckDuckGo. All rights reserved. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// | ||
|
||
import BrowserServicesKit | ||
import Foundation | ||
|
||
public class MockVariant: Variant { | ||
public var name: String | ||
public var weight: Int | ||
public var isIncluded: () -> Bool | ||
public var features: [FeatureName] | ||
|
||
public init(name: String, weight: Int, isIncluded: @escaping () -> Bool, features: [FeatureName]) { | ||
self.name = name | ||
self.weight = weight | ||
self.isIncluded = isIncluded | ||
self.features = features | ||
} | ||
} |
Oops, something went wrong.