commit 9620bda9723daf144bdcbff6c2973f99886b96a0
parent ee6f3d3238c2ac4030f8be1f5dd529d113696ca7
Author: Irene Ni <rhn0312@gmail.com>
Date: Wed, 7 Jan 2026 22:23:55 +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:
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