Bug 1859265 - Update cached metadata before updating add-ons. r=rpl,amejiamarmol,geckoview-reviewers

We currently do not refresh the cached metadata in the add-ons
repository because the update timer isn't enabled on Android.

This patch calls the add-ons repository update logic to refresh
the cached metadata when an add-on is checked for updates. This
is similar to what we're doing when we perform a (full) background
update check on Desktop.

Differential Revision: https://phabricator.services.mozilla.com/D191081
This commit is contained in:
William Durand 2023-10-16 18:41:53 +00:00
Родитель 54d433ca37
Коммит 6da195e1ff
3 изменённых файлов: 74 добавлений и 1 удалений

Просмотреть файл

@ -7,6 +7,7 @@ package org.mozilla.geckoview.test
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.greaterThan
import org.hamcrest.core.IsEqual.equalTo
import org.hamcrest.core.StringEndsWith.endsWith
import org.json.JSONObject
@ -2258,6 +2259,8 @@ class WebExtensionTest : BaseSessionTest() {
"xpinstall.signatures.required" to false,
"extensions.install.requireBuiltInCerts" to false,
"extensions.update.requireBuiltInCerts" to false,
"extensions.getAddons.cache.enabled" to true,
"extensions.getAddons.cache.lastUpdate" to 0,
),
)
mainSession.loadUri("https://example.com")
@ -2303,6 +2306,52 @@ class WebExtensionTest : BaseSessionTest() {
// Check that the WebExtension was not applied after being uninstalled
assertBodyBorderEqualTo("")
// This pref should have been updated because we expect the cached
// metadata to have been refreshed.
val geckoPrefs = sessionRule.getPrefs(
"extensions.getAddons.cache.lastUpdate",
)
assumeThat(geckoPrefs[0] as Int, greaterThan(0))
}
@Test
fun updateWithMetadataNotStale() {
val now = (System.currentTimeMillis() / 1000).toInt()
sessionRule.setPrefsUntilTestEnd(
mapOf(
"xpinstall.signatures.required" to false,
"extensions.install.requireBuiltInCerts" to false,
"extensions.update.requireBuiltInCerts" to false,
"extensions.getAddons.cache.enabled" to true,
"extensions.getAddons.cache.lastUpdate" to now,
),
)
sessionRule.delegateDuringNextWait(object : WebExtensionController.PromptDelegate {
@AssertCalled
override fun onInstallPrompt(extension: WebExtension): GeckoResult<AllowOrDeny> {
assertEquals(extension.metaData.version, "1.0")
return GeckoResult.allow()
}
})
// 1. Install
val update1 = sessionRule.waitForResult(
controller.install("https://example.org/tests/junit/update-1.xpi"),
)
// 2. Update
val update2 = sessionRule.waitForResult(controller.update(update1))
// 3. Uninstall
sessionRule.waitForResult(controller.uninstall(update2))
// This pref should not have been updated because the cache isn't stale
// (we set the pref to the current time at the top of this test case).
val geckoPrefs = sessionRule.getPrefs(
"extensions.getAddons.cache.lastUpdate",
)
assumeThat(geckoPrefs[0] as Int, equalTo(now))
}
// Test extension updating when the new extension has different permissions.

Просмотреть файл

@ -15,6 +15,7 @@ const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
AddonManager: "resource://gre/modules/AddonManager.sys.mjs",
AddonRepository: "resource://gre/modules/addons/AddonRepository.sys.mjs",
AddonSettings: "resource://gre/modules/addons/AddonSettings.sys.mjs",
EventDispatcher: "resource://gre/modules/Messaging.sys.mjs",
Extension: "resource://gre/modules/Extension.sys.mjs",
@ -1065,6 +1066,20 @@ export var GeckoViewWebExtension = {
},
async updateWebExtension(aId) {
// Refresh the cached metadata when necessary. This allows us to always
// export relatively recent metadata to the embedder.
if (lazy.AddonRepository.isMetadataStale()) {
// We use a promise to avoid more than one call to `backgroundUpdateCheck()`
// when `updateWebExtension()` is called for multiple add-ons in parallel.
if (!this._promiseAddonRepositoryUpdate) {
this._promiseAddonRepositoryUpdate =
lazy.AddonRepository.backgroundUpdateCheck().finally(() => {
this._promiseAddonRepositoryUpdate = null;
});
}
await this._promiseAddonRepositoryUpdate;
}
const extension = await this.extensionById(aId);
const install = await this.checkForUpdate(extension);

Просмотреть файл

@ -644,7 +644,16 @@ export var AddonRepository = {
},
/**
* Performs the daily background update check.
* Performs the periodic background update check.
*
* In Firefox Desktop builds, the background update check is triggered on a
* daily basis as part of the AOM background update check and registered
* from: `toolkit/mozapps/extensions/extensions.manifest`
*
* In GeckoView builds, add-ons are checked for updates individually. The
* `AddonRepository.backgroundUpdateCheck()` method is called by the
* `updateWebExtension()` method defined in `GeckoViewWebExtensions.sys.mjs`
* but only when `AddonRepository.isMetadataStale()` returns true.
*
* @return Promise{null} Resolves when the metadata update is complete.
*/