tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 05874864bfe4325ec857ade6b539f152c2fa5bd1
parent bf17dfb09e817999a6e99bc251b71dbdc709d8d9
Author: Mike Conley <mconley@mozilla.com>
Date:   Fri, 24 Oct 2025 20:10:59 +0000

Bug 1996324 - Part 2: Add the newtab addon version to about:home startup cache metadata, and check it on initialization. r=home-newtab-reviewers,thecount

Differential Revision: https://phabricator.services.mozilla.com/D270039

Diffstat:
Mbrowser/components/newtab/AboutHomeStartupCache.sys.mjs | 55++++++++++++++++++++++++++++++++++++++++++++++++++++---
Mbrowser/components/newtab/test/browser/abouthomecache/browser.toml | 2++
Abrowser/components/newtab/test/browser/abouthomecache/browser_bump_newtab_version.js | 39+++++++++++++++++++++++++++++++++++++++
3 files changed, 93 insertions(+), 3 deletions(-)

diff --git a/browser/components/newtab/AboutHomeStartupCache.sys.mjs b/browser/components/newtab/AboutHomeStartupCache.sys.mjs @@ -5,6 +5,8 @@ let lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { AboutNewTab: "resource:///modules/AboutNewTab.sys.mjs", + AboutNewTabResourceMapping: + "resource:///modules/AboutNewTabResourceMapping.sys.mjs", AsyncShutdown: "resource://gre/modules/AsyncShutdown.sys.mjs", DeferredTask: "resource://gre/modules/DeferredTask.sys.mjs", E10SUtils: "resource://gre/modules/E10SUtils.sys.mjs", @@ -37,6 +39,10 @@ export var AboutHomeStartupCache = { // The version is currently set to the build ID, meaning that the cache // is invalidated after every upgrade (like the main startup cache). CACHE_VERSION_META_KEY: "version", + // Similar, with newtab now able to update out-of-band from the rest of the + // application, it's possible that the newtab version has changed since the + // cache was written. If so, we should ignore the cache. + CACHE_NEWTAB_VERSION_META_KEY: "newtab-version", LOG_NAME: "AboutHomeStartupCache", @@ -458,7 +464,9 @@ export var AboutHomeStartupCache = { ); } catch (e) { if (e.result == Cr.NS_ERROR_NOT_AVAILABLE) { - this.log.debug("Cache meta data does not exist. Closing streams."); + this.log.debug( + "Cache meta data for version does not exist. Closing streams." + ); this.pagePipe.outputStream.close(); this.scriptPipe.outputStream.close(); this.setDeferredResult(this.CACHE_RESULT_SCALARS.DOES_NOT_EXIST); @@ -471,7 +479,38 @@ export var AboutHomeStartupCache = { this.log.info("Version retrieved is", version); if (version != Services.appinfo.appBuildID) { - this.log.info("Version does not match! Dooming and closing streams.\n"); + this.log.info("Version does not match! Dooming and closing streams."); + // This cache is no good - doom it, and prepare for a new one. + this.clearCache(); + this.pagePipe.outputStream.close(); + this.scriptPipe.outputStream.close(); + this.setDeferredResult(this.CACHE_RESULT_SCALARS.INVALIDATED); + return; + } + + let newtabVersion; + try { + newtabVersion = this._cacheEntry.getMetaDataElement( + this.CACHE_NEWTAB_VERSION_META_KEY + ); + } catch (e) { + if (e.result == Cr.NS_ERROR_NOT_AVAILABLE) { + this.log.debug( + "Cache meta data for newtab version does not exist. Closing streams." + ); + this.pagePipe.outputStream.close(); + this.scriptPipe.outputStream.close(); + this.setDeferredResult(this.CACHE_RESULT_SCALARS.DOES_NOT_EXIST); + return; + } + + throw e; + } + + if (newtabVersion != lazy.AboutNewTabResourceMapping.addonVersion) { + this.log.info( + "New Tab version does not match! Dooming and closing streams." + ); // This cache is no good - doom it, and prepare for a new one. this.clearCache(); this.pagePipe.outputStream.close(); @@ -607,7 +646,7 @@ export var AboutHomeStartupCache = { ); try { this._cacheEntry.setMetaDataElement( - "version", + this.CACHE_VERSION_META_KEY, Services.appinfo.appBuildID ); } catch (e) { @@ -615,6 +654,16 @@ export var AboutHomeStartupCache = { reject(e); return; } + try { + this._cacheEntry.setMetaDataElement( + this.CACHE_NEWTAB_VERSION_META_KEY, + lazy.AboutNewTabResourceMapping.addonVersion + ); + } catch (e) { + this.log.error("Failed to write newtab version."); + reject(e); + return; + } this.log.trace(`Version is set to ${Services.appinfo.appBuildID}.`); this.log.info("Caching of page and script is done."); resolve(); diff --git a/browser/components/newtab/test/browser/abouthomecache/browser.toml b/browser/components/newtab/test/browser/abouthomecache/browser.toml @@ -23,6 +23,8 @@ prefs = [ ["browser_basic_endtoend.js"] +["browser_bump_newtab_version.js"] + ["browser_bump_version.js"] ["browser_clearCacheAndUninit.js"] diff --git a/browser/components/newtab/test/browser/abouthomecache/browser_bump_newtab_version.js b/browser/components/newtab/test/browser/abouthomecache/browser_bump_newtab_version.js @@ -0,0 +1,39 @@ +/* Any copyright is dedicated to the Public Domain. + https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const { AboutNewTabResourceMapping } = ChromeUtils.importESModule( + "resource:///modules/AboutNewTabResourceMapping.sys.mjs" +); + +/** + * Test that if the "newtab-version" metadata on the cache entry doesn't match + * the expectation that we ignore the cache and load the dynamic about:home + * document. + */ +add_task(async function test_newtab_bump_version() { + await withFullyLoadedAboutHome(async browser => { + // First, ensure that a pre-existing cache exists. + await simulateRestart(browser); + + let cacheEntry = await AboutHomeStartupCache.ensureCacheEntry(); + Assert.equal( + cacheEntry.getMetaDataElement("newtab-version"), + AboutNewTabResourceMapping.addonVersion, + "Cache entry should be versioned on the newtab version" + ); + cacheEntry.setMetaDataElement("newtab-version", "somethingnew"); + // We don't need to shutdown write or ensure the cache wins the race, + // since we expect the cache to be blown away because the version number + // has been bumped. + await simulateRestart(browser, { + withAutoShutdownWrite: false, + ensureCacheWinsRace: false, + }); + await ensureDynamicAboutHome( + browser, + AboutHomeStartupCache.CACHE_RESULT_SCALARS.INVALIDATED + ); + }); +});