tor-browser

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

commit f063a98a3dbb6ade3fc46694c7ac9f9946874612
parent cd18695e48ac25a4d6e14b794aac886e52386a2a
Author: Irene Ni <rhn0312@gmail.com>
Date:   Wed,  7 Jan 2026 15:47:43 +0000

Bug 2002144 - Replace New Tab Wallpaper blob URLs with MozNewTabWallpaper protocol handler. r=mconley,home-newtab-reviewers

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

Diffstat:
Mbrowser/extensions/newtab/lib/Wallpapers/WallpaperFeed.sys.mjs | 108+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Mbrowser/extensions/newtab/test/xpcshell/test_WallpaperFeed.js | 28++++++++++++++++------------
2 files changed, 91 insertions(+), 45 deletions(-)

diff --git a/browser/extensions/newtab/lib/Wallpapers/WallpaperFeed.sys.mjs b/browser/extensions/newtab/lib/Wallpapers/WallpaperFeed.sys.mjs @@ -2,6 +2,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs"; + const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { BasePromiseWorker: "resource://gre/modules/PromiseWorker.sys.mjs", @@ -37,12 +39,22 @@ const RS_FALLBACK_BASE_URL = export class WallpaperFeed { #customBackgroundObjectURL = null; + // @backward-compat { version 148 } This newtab train-hop compatibility + // shim can be removed once Firefox 148 makes it to the release channel. + #usesProtocolHandler = + Services.vc.compare(AppConstants.MOZ_APP_VERSION, "148.0a1") >= 0; + constructor() { this.loaded = false; this.wallpaperClient = null; this._onSync = this.onSync.bind(this); } + // Constructs a moz-newtab-wallpaper:// URI for the given wallpaper UUID. + getWallpaperURL(uuid) { + return `moz-newtab-wallpaper://${uuid}`; + } + /** * This thin wrapper around global.fetch makes it easier for us to write * automated tests that simulate responses from this fetch. @@ -99,6 +111,15 @@ export class WallpaperFeed { } async updateWallpapers(isStartup = false) { + // @backward-compat { version 148 } This newtab train-hop compatibility + // shim can be removed once Firefox 148 makes it to the release channel. + if (!this.#usesProtocolHandler) { + if (this.#customBackgroundObjectURL) { + URL.revokeObjectURL(this.#customBackgroundObjectURL); + this.#customBackgroundObjectURL = null; + } + } + let uuid = Services.prefs.getStringPref( PREF_WALLPAPERS_CUSTOM_WALLPAPER_UUID, "" @@ -109,35 +130,43 @@ export class WallpaperFeed { "" ); - if (this.#customBackgroundObjectURL) { - URL.revokeObjectURL(this.#customBackgroundObjectURL); - this.#customBackgroundObjectURL = null; - } - if (uuid && selectedWallpaper === "custom") { - const wallpaperDir = PathUtils.join(PathUtils.profileDir, "wallpaper"); - const filePath = PathUtils.join(wallpaperDir, uuid); - - try { - let testFile = await IOUtils.getFile(filePath); - - if (!testFile) { - throw new Error("File does not exist"); - } - - let imageFile = await File.createFromNsIFile(testFile); - this.#customBackgroundObjectURL = URL.createObjectURL(imageFile); + // @backward-compat { version 148 } This newtab train-hop compatibility + // shim can be removed once Firefox 148 makes it to the release channel. + if (this.#usesProtocolHandler) { + const wallpaperURI = this.getWallpaperURL(uuid); this.store.dispatch( ac.BroadcastToContent({ type: at.WALLPAPERS_CUSTOM_SET, - data: this.#customBackgroundObjectURL, + data: wallpaperURI, }) ); - } catch (error) { - console.warn(`Wallpaper file not found: ${error.message}`); - Services.prefs.clearUserPref(PREF_WALLPAPERS_CUSTOM_WALLPAPER_UUID); - return; + } else { + const wallpaperDir = PathUtils.join(PathUtils.profileDir, "wallpaper"); + const filePath = PathUtils.join(wallpaperDir, uuid); + + try { + let testFile = await IOUtils.getFile(filePath); + + if (!testFile) { + throw new Error("File does not exist"); + } + + let imageFile = await File.createFromNsIFile(testFile); + this.#customBackgroundObjectURL = URL.createObjectURL(imageFile); + + this.store.dispatch( + ac.BroadcastToContent({ + type: at.WALLPAPERS_CUSTOM_SET, + data: this.#customBackgroundObjectURL, + }) + ); + } catch (error) { + console.warn(`Wallpaper file not found: ${error.message}`); + Services.prefs.clearUserPref(PREF_WALLPAPERS_CUSTOM_WALLPAPER_UUID); + return; + } } } else { this.store.dispatch( @@ -281,19 +310,32 @@ export class WallpaperFeed { await IOUtils.write(filePath, uint8Array, { tmpPath: `${filePath}.tmp` }); - if (this.#customBackgroundObjectURL) { - URL.revokeObjectURL(this.#customBackgroundObjectURL); - this.#customBackgroundObjectURL = null; - } + // @backward-compat { version 148 } This newtab train-hop compatibility + // shim can be removed once Firefox 148 makes it to the release channel. + if (this.#usesProtocolHandler) { + const wallpaperURI = this.getWallpaperURL(uuid); - this.#customBackgroundObjectURL = URL.createObjectURL(file); + this.store.dispatch( + ac.BroadcastToContent({ + type: at.WALLPAPERS_CUSTOM_SET, + data: wallpaperURI, + }) + ); + } else { + if (this.#customBackgroundObjectURL) { + URL.revokeObjectURL(this.#customBackgroundObjectURL); + this.#customBackgroundObjectURL = null; + } - this.store.dispatch( - ac.BroadcastToContent({ - type: at.WALLPAPERS_CUSTOM_SET, - data: this.#customBackgroundObjectURL, - }) - ); + this.#customBackgroundObjectURL = URL.createObjectURL(file); + + this.store.dispatch( + ac.BroadcastToContent({ + type: at.WALLPAPERS_CUSTOM_SET, + data: this.#customBackgroundObjectURL, + }) + ); + } this.store.dispatch( ac.SetPref("newtabWallpapers.customWallpaper.theme", wallpaperTheme) diff --git a/browser/extensions/newtab/test/xpcshell/test_WallpaperFeed.js b/browser/extensions/newtab/test/xpcshell/test_WallpaperFeed.js @@ -202,10 +202,10 @@ add_task(async function test_Wallpaper_Upload() { }); /** - * Tests that the parent process sends down a consistent object URL to newtab to - * render as the background. + * Tests that the parent process sends down a moz-newtab-wallpaper:// protocol URI + * to newtab to render as the background. */ -add_task(async function test_Wallpaper_objectURI() { +add_task(async function test_Wallpaper_protocolURI() { let sandbox = sinon.createSandbox(); let feed = getWallpaperFeedForTest(sandbox); @@ -243,22 +243,26 @@ add_task(async function test_Wallpaper_objectURI() { feed.store.dispatch.calledWith( actionCreators.BroadcastToContent({ type: actionTypes.WALLPAPERS_CUSTOM_SET, - data: sandbox.match("blob:null/"), + data: sandbox.match("moz-newtab-wallpaper://"), }) - ) + ), + "Should dispatch WALLPAPERS_CUSTOM_SET with moz-newtab-wallpaper:// URI" ); - // Now ensure that a consistent object URL gets returned for each subsequent - // request for a wallpaper by checking to see that it exists in the state - // object. This URL is non-deterministic, but we can pull it out from what was - // just passed to the store dispatch method. + // Verify the protocol URI uses the correct scheme and gets stored in state const [action] = feed.store.dispatch.getCall(0).args; - const wallpaperURL = action.data; + const wallpaperURI = action.data; + + Assert.ok( + wallpaperURI.startsWith("moz-newtab-wallpaper://"), + "Wallpaper URI should use moz-newtab-wallpaper:// protocol" + ); + const state = reducers.Wallpapers(null, action); Assert.equal( state.uploadedWallpaper, - wallpaperURL, - "Should have updated the state to include the object URL" + wallpaperURI, + "Should have updated the state to include the protocol URI" ); // Cleanup files