Skip to content
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

Make remote config accessible to background agents #3255

Merged
merged 22 commits into from
Sep 17, 2024

Conversation

SlayterDev
Copy link
Contributor

@SlayterDev SlayterDev commented Aug 20, 2024

Task/Issue URL: https://app.asana.com/0/1203581873609357/1207165680693234/f
Tech Design URL:
CC:

Description:

Steps to test this PR:

  1. See Make remote config accessible to background agents BrowserServicesKit#947

Definition of Done (Internal Only):

Copy Testing:

  • Use of correct apostrophes in new copy, ie rather than '

Orientation Testing:

  • Portrait
  • Landscape

Device Testing:

  • iPhone SE (1st Gen)
  • iPhone 8
  • iPhone X
  • iPhone 14 Pro
  • iPad

OS Testing:

  • iOS 15
  • iOS 16
  • iOS 17

Theme Testing:

  • Light theme
  • Dark theme

Internal references:

Software Engineering Expectations
Technical Design Template

@SlayterDev SlayterDev reopened this Sep 5, 2024
@SlayterDev SlayterDev marked this pull request as ready for review September 5, 2024 14:38
Copy link

github-actions bot commented Sep 5, 2024

Warnings
⚠️ PR has more than 500 lines of code changing. Consider splitting into smaller PRs if possible.

Generated by 🚫 dangerJS against 9c75b69

Core/FileStore.swift Outdated Show resolved Hide resolved
var coordinatorError: NSError?
var writeError: Error?

NSFileCoordinator().coordinate(writingItemAt: file, options: .forReplacing, error: &coordinatorError) { fileUrl in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's check that this persist function overall is never called on the main thread, since the coordinate function will block that thread until it can complete what it's trying to do.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tracked the persist calls all the way up to here. Basically the full fetch then store process is initiated by the AppConfigurationFetch within a Task. AFAIK that should put it off the main thread.

Core/PixelEvent.swift Outdated Show resolved Hide resolved
Comment on lines +340 to +342
if privacyConfigurationManager.privacyConfig.isSubfeatureEnabled(BackgroundAgentPixelTestSubfeature.pixelTest) {
DailyPixel.fire(pixel: .networkProtectionConfigurationPixelTest)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's possible we'll still miss calls to this pixel - this publisher is only called when we receive updates, so if no Privacy Config update is published on a given day then we'll get no events coming through.

We could probably add the BackgroundAgentPixelTestSubfeature.pixelTest check and pixel call somewhere that we know will get called regularly, like handleConnectionStatusChange. That said, we only really care about getting these calls on days where we're changing the rollout param and at that point we will get this publisher called, so I'd be fine with it staying as-is.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Struggling a bit to follow what pixelTest is.

Comment on lines +32 to +49
var embeddedConfigData: Data {
let configString = """
{
"readme": "https://github.com/duckduckgo/privacy-configuration",
"version": 1693838894358,
"features": {
"networkProtection": {
"state": "enabled",
"exceptions": [],
"settings": {}
}
},
"unprotectedTemporary": []
}
"""
let data = configString.data(using: .utf8)
return data!
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should close this gap as quickly as possible; from my perspective we can live with this in the short term, at least as part of running the pixel rollout test, but I'd advocate for us getting real embedded data working ASAP. Would you be able to scope the changes required for this for both iOS and macOS?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class could use unit tests, though I acknowledge there's no good test suite set up for it right now. I'll defer to @diegoreymendez on whether he'd like to block on this, as primary of the VPN AOR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree that it'd be ideal to have tests here, but I'm not confident the effort to implement those tests is worth additional delay here. Especially because the effort involved isn't completely clear to me and I don't want to be blocking things here.

Copy link
Contributor

@samsymons samsymons left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving based on the behavior working well for me across a bunch of different test cases.

Copy link
Contributor

@diegoreymendez diegoreymendez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some comments. Mostly questions I have.

private let defaults = UserDefaults(suiteName: "com.duckduckgo.blocker-list.etags")
private let defaults = UserDefaults(suiteName: "\(Global.groupIdPrefix).app-configuration")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a risky transition / migration? We're moving from using an existing user defaults suite, to using a new one.

Is there anything stored here that will get reset that might cause trouble for users?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think there's a risk here. Configuration starts up and fetches all configs at app launch. For an app update this will look like a fresh install for the configs. It will see no etags and just fetch the current versions and store them. I haven't run in to any issues during testing which involved a "migration".

@@ -22,16 +22,30 @@ import Configuration

public class FileStore {

private let groupIdentifier: String = ContentBlockerStoreConstants.groupName
private let groupIdentifier: String = ContentBlockerStoreConstants.configurationGroupName
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is used for the file paths: is there anything that will get reset here that might cause trouble for users?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the etags. The module will see no files and download fresh ones. In the case of content blocking/privacy config we have embedded fallbacks while we wait for downloads.

Core/UserDefaults+NetworkProtection.swift Outdated Show resolved Hide resolved
@@ -519,6 +519,7 @@ import os.log
ContentBlocking.shared.contentBlockingManager.scheduleCompilation()
AppConfigurationFetch.shouldScheduleRulesCompilationOnAppLaunch = false
}
AppDependencyProvider.shared.configurationManager.loadPrivacyConfigFromDiskIfNeeded()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this happen before AppDependencyProvider.shared.configurationManager is used in line 295?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't matter. We don't use the built in timer of the configuration manager because of background app refresh. And even if we did the only purpose of this method is to diff the stored etag vs the etag in the privacy config manager and load fresh from disk if needed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree that it'd be ideal to have tests here, but I'm not confident the effort to implement those tests is worth additional delay here. Especially because the effort involved isn't completely clear to me and I don't want to be blocking things here.

Comment on lines +340 to +342
if privacyConfigurationManager.privacyConfig.isSubfeatureEnabled(BackgroundAgentPixelTestSubfeature.pixelTest) {
DailyPixel.fire(pixel: .networkProtectionConfigurationPixelTest)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Struggling a bit to follow what pixelTest is.

Copy link
Contributor

@diegoreymendez diegoreymendez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing more to add, my main doubts have been covered here.

SlayterDev added a commit to duckduckgo/BrowserServicesKit that referenced this pull request Sep 17, 2024
<!--
Note: This checklist is a reminder of our shared engineering
expectations.
-->

Please review the release process for BrowserServicesKit
[here](https://app.asana.com/0/1200194497630846/1200837094583426).

**Required**:

Task/Issue URL:
https://app.asana.com/0/1203581873609357/1207165680693234/f
iOS PR: duckduckgo/iOS#3255
macOS PR: duckduckgo/macos-browser#3124
What kind of version bump will this require?: Major
**Optional**:

Tech Design URL:
CC:

**Description**:
This PR modularizes the config to allow it to be used in background
processes

<!--
Tagging instructions
If this PR isn't ready to be merged for whatever reason it should be
marked with the `DO NOT MERGE` label (particularly if it's a draft)
If it's pending Product Review/PFR, please add the `Pending Product
Review` label.

If at any point it isn't actively being worked on/ready for
review/otherwise moving forward (besides the above PR/PFR exception)
strongly consider closing it (or not opening it in the first place). If
you decide not to close it, make sure it's labelled to make it clear the
PRs state and comment with more information.
-->

**Steps to test this PR**:
1. Run the VPN and DBP background agents
2. Look for `Configuration` logs that indicate the config being
downloaded or refreshed
3. If the config is setup correctly you can watch for the pixel test as
well.
1.

<!--
Before submitting a PR, please ensure you have tested the combinations
you expect the reviewer to test, then delete configurations you *know*
do not need explicit testing.

Using a simulator where a physical device is unavailable is acceptable.
-->

**OS Testing**:

* [ ] iOS 14
* [ ] iOS 15
* [ ] iOS 16
* [ ] macOS 10.15
* [ ] macOS 11
* [ ] macOS 12

---
###### Internal references:
[Software Engineering
Expectations](https://app.asana.com/0/59792373528535/199064865822552)
[Technical Design
Template](https://app.asana.com/0/59792373528535/184709971311943)
@SlayterDev SlayterDev merged commit 2905855 into main Sep 17, 2024
13 checks passed
@SlayterDev SlayterDev deleted the brad/background-config branch September 17, 2024 15:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants