-
Notifications
You must be signed in to change notification settings - Fork 35
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
Remote Messaging Framework for macOS #876
Conversation
Package.swift
Outdated
@@ -166,6 +166,12 @@ let package = Package( | |||
.define("DEBUG", .when(configuration: .debug)) | |||
] | |||
), | |||
.target( | |||
name: "EmailTestsUtils", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EmailTestUtils contains EmailManager related mocks that are moved over from BrowserServicesKit so as to avoid making RemoteMessagingTests dependent on BrowserServicesKit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EDIT: I renamed it as BrowserServicesKitTestsUtils
to indicate that these are mocks of classes from BrowserServicesKit
module. Also moved there StatisticsStore, Variant and VariantManager mocks.
@@ -272,6 +279,13 @@ let package = Package( | |||
.define("DEBUG", .when(configuration: .debug)) | |||
] | |||
), | |||
.target( | |||
name: "RemoteMessagingTestsUtils", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RemoteMessagingTestsUtils contains mocks for RemoteMessaging related protocols
@@ -400,7 +414,7 @@ let package = Package( | |||
name: "BrowserServicesKitTests", | |||
dependencies: [ | |||
"BrowserServicesKit", | |||
"RemoteMessaging", // Move tests later (lots of test dependencies in BSK) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RemoteMessaging has its own tests target now.
@@ -184,6 +184,31 @@ public struct BookmarkUtils { | |||
return result.compactMap { $0[#keyPath(BookmarkEntity.title)] as? String } | |||
} | |||
|
|||
public static func numberOfBookmarks(in context: NSManagedObjectContext) -> Int { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These 2 functions were used exclusively for RMF in the iOS repo. Now they're in BookmarkUtils and can be reused by macOS.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 2 files in EmailTestUtils are moved 1:1 from EmailManagerTests.swift in BrowserServicesKit
|
||
} | ||
|
||
public struct CommonUserAttributeMatcher: AttributeMatching { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Common matcher defines matching mechanism for all attributes that are supported by both iOS and macOS.
@@ -27,7 +27,7 @@ private enum RuleAttributes { | |||
static let since = "since" | |||
} | |||
|
|||
protocol MatchingAttribute { | |||
public protocol MatchingAttribute { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AttributeMatching was made public. Since it uses MatchingAttribute, this one needs to be made public as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has been replaced by RemoteMessagingConfigFetcher that uses ConfigurationFetcher/Store.
let context: NSManagedObjectContext | ||
let database: CoreDataDatabase |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change makes the functions in RemoteMessagingStore create context as needed, ensuring that they have the fresh data all the time. We use a similar approach in Sync Bookmarks provider.
@@ -19,12 +19,17 @@ | |||
import Foundation | |||
import RemoteMessaging | |||
|
|||
class MockRemoteMessagePercentileStore: RemoteMessagingPercentileStoring { | |||
public class MockRemoteMessagePercentileStore: RemoteMessagingPercentileStoring { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mocks moved to a dedicated mocks target (RemoteMessagingTestsUtils in this case) need to be made public so that the module could be imported without @testable
…n RMF becomes disabled
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks solid :)
return | ||
} | ||
do { | ||
let statusResponse = try await configurationFetcher.fetchRemoteMessagingConfig() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this might be some old naming, where this func used to return status code or something? But now it is config indeed, isn't it?
I would actually suggest a couple of helper func here to make this functionality here more readable, e.g:
private func fetchRemoteMessagingConfig() async throws -> RemoteMessagingConfig
private func processRemoteMessagingConfig(_ config: RemoteMessagingConfig, using store: RemoteMessagingStoring) async throws -> ProcessedResult
where first func just implements: try await configurationFetcher.fetchRemoteMessagingConfig()
second: pretty much old the rest
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Yeah, I agree it's a bit messy. This function used to be called fetchRemoteMessages
. Now I've renamed it but failed to notice that there are two fetchRemoteMessagingConfig
functions being called here, from 2 different protocols 🤦 and they do 2 different things, first one fetches the config from the server, and the second one fetches config metadata from the local database. 😬
Let me try to make it right :)
if let processorResult = processor.process(jsonRemoteMessagingConfig: statusResponse, currentConfig: config) { | ||
store.saveProcessedResult(processorResult) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps this should be guard that throws some processing failed error? otherwise we're not getting any debug info what happened
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method calls a bunch of Store private methods inside, each of which can throw an error that is handled by sending a pixel (via EventMapping
) and printing a console log. So I think it's acceptable. I agree that it's not ideal though.
Also, this function's error is silenced at the call site (with try?
– again probably acceptable in this specific case because it effectively silences only network and JSON parsing errors). I may propose an update to this piece of code but it has been a status quo for past 2 years so I'd rather handle it separately.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't bother, makes sense to me
* main: Remove unused VPN session utilities (#898) Add new deprecated Mac remote message attribute. (#903) Resetting all state for the VPN will cancel the tunnel and stop the monitors (#900) Add support for skipping sending usage pixels for remote messages (#902) Bump Tests/BrowserServicesKitTests/Resources/privacy-reference-tests (#896) Removes the listen port from the wireguard client (#901) Be explicit when performing developer redirects (#884) C-S-S cross origin fixes Update C-S-S version (#892) Add a debug menu action to reset Remote Messages on macOS (#891) Add desktop specific RMF attributes (#883) Upload exception message to Sentry (#856) Add locale to broken site report (#889) Add new subfeature for duckplayer (#885) Swiftlint refactoring (#882) Remote Messaging Framework for macOS (#876)
Please review the release process for BrowserServicesKit here.
Required:
Task/Issue URL: https://app.asana.com/0/72649045549333/1202913520695928/f
iOS PR: duckduckgo/iOS#3031
macOS PR: duckduckgo/macos-browser#2937
What kind of version bump will this require?: Major
Optional:
CC: @amddg44 @samsymons
Description:
This change adds support for RMF on macOS.
(most importantly RemoteMessagingProcessing protocol).
to create and return the config matcher filled with current values of matching attributes.
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).
and supports Etags.
and RemoteMessagingTests (that also mandated creating EmailTestsUtils).
to ensure it always gets the freshest data from the persistent store.
Steps to test this PR:
See iOS PR for steps to test.
OS Testing:
Internal references:
Software Engineering Expectations
Technical Design Template