commit 316685cef67b05ddb400b8ec64b2eb0cf3a8c74e
parent 566e4283c6b13cec5a7837c93822ba4b64e3fae1
Author: Sebastian Streich <sstreich@mozilla.com>
Date: Tue, 18 Nov 2025 21:17:02 +0000
Bug 1997912 - IPProtectionServerlist should update on RemoteSettings Sync r=ip-protection-reviewers,baku
Differential Revision: https://phabricator.services.mozilla.com/D271054
Diffstat:
2 files changed, 48 insertions(+), 5 deletions(-)
diff --git a/browser/components/ipprotection/IPProtectionServerlist.sys.mjs b/browser/components/ipprotection/IPProtectionServerlist.sys.mjs
@@ -186,6 +186,7 @@ class Country {
class IPProtectionServerlistSingleton {
#list = null;
#runningPromise = null;
+ #bucket = null;
constructor() {
this.handleEvent = this.#handleEvent.bind(this);
@@ -201,7 +202,11 @@ class IPProtectionServerlistSingleton {
);
}
- async initOnStartupCompleted() {}
+ async initOnStartupCompleted() {
+ this.bucket.on("sync", async () => {
+ await this.maybeFetchList(true);
+ });
+ }
uninit() {
lazy.IPProtectionService.removeEventListener(
@@ -216,8 +221,8 @@ class IPProtectionServerlistSingleton {
}
}
- maybeFetchList() {
- if (this.#list.length !== 0) {
+ maybeFetchList(forceUpdate = false) {
+ if (this.#list.length !== 0 && !forceUpdate) {
return Promise.resolve();
}
@@ -226,9 +231,8 @@ class IPProtectionServerlistSingleton {
}
const fetchList = async () => {
- const bucket = lazy.RemoteSettings("vpn-serverlist");
this.#list = IPProtectionServerlistSingleton.#dataToList(
- await bucket.get()
+ await this.bucket.get()
);
lazy.IPPStartupCache.storeLocationList(this.#list);
@@ -287,6 +291,13 @@ class IPProtectionServerlistSingleton {
return this.#list.length !== 0;
}
+ get bucket() {
+ if (!this.#bucket) {
+ this.#bucket = lazy.RemoteSettings("vpn-serverlist");
+ }
+ return this.#bucket;
+ }
+
static #dataToList(list) {
if (!Array.isArray(list)) {
return [];
diff --git a/browser/components/ipprotection/tests/xpcshell/test_IPProtectionServerlist.js b/browser/components/ipprotection/tests/xpcshell/test_IPProtectionServerlist.js
@@ -85,6 +85,7 @@ add_setup(async function () {
await client.db.importChanges({}, Date.now());
await IPProtectionServerlist.maybeFetchList();
+ await IPProtectionServerlist.initOnStartupCompleted();
});
add_task(async function test_getDefaultLocation() {
@@ -145,3 +146,34 @@ add_task(async function test_selectServer() {
selected = IPProtectionServerlist.selectServer(cityWithNoServers);
Assert.equal(selected, null, "No server should be selected");
});
+
+add_task(async function test_syncRespected() {
+ let { country, city } = IPProtectionServerlist.getDefaultLocation();
+ Assert.equal(country.code, "US", "The default country should be US");
+ Assert.deepEqual(city, TEST_US_CITY, "The correct city should be returned");
+
+ // Now, update the server list to remove the US entry
+ const updated_server = {
+ ...TEST_SERVER_1,
+ hostname: "updated.example.com",
+ };
+ const updated_city = {
+ ...TEST_US_CITY,
+ servers: [updated_server],
+ };
+ const updated_country = {
+ ...TEST_COUNTRIES[0],
+ cities: [updated_city],
+ };
+
+ await client.db.clear();
+ await client.db.create(updated_country);
+ await client.db.importChanges({}, Date.now());
+ await client.emit("sync", { data: {} });
+
+ await IPProtectionServerlist.maybeFetchList();
+
+ ({ country, city } = IPProtectionServerlist.getDefaultLocation());
+ Assert.equal(country.code, "US", "The default country should be US");
+ Assert.deepEqual(city, updated_city, "The updated city should be returned");
+});