/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; ChromeUtils.defineESModuleGetters(this, { sinon: "resource://testing-common/Sinon.sys.mjs", ShellService: "moz-src:///browser/components/shell/ShellService.sys.mjs", TaskbarTabsPin: "resource:///modules/taskbartabs/TaskbarTabsPin.sys.mjs", TaskbarTabsRegistry: "resource:///modules/taskbartabs/TaskbarTabsRegistry.sys.mjs", TaskbarTabsUtils: "resource:///modules/taskbartabs/TaskbarTabsUtils.sys.mjs", XPCOMUtils: "resource://gre/modules/XPCOMUtils.sys.mjs", }); XPCOMUtils.defineLazyServiceGetters(this, { imgTools: ["@mozilla.org/image/tools;1", Ci.imgITools], }); // We want to mock the native XPCOM interfaces of the initialized // `ShellService.shellService`, but those interfaces are frozen. Instead we // proxy `ShellService.shellService` and mock it. let gWriteShortcutIcon = ShellService.writeShortcutIcon; let gOverrideIconFileOnce; const kMockNativeShellService = { ...ShellService.shellService, createShortcut: sinon.stub().resolves("dummy_path"), deleteShortcut: sinon.stub().resolves("dummy_path"), pinShortcutToTaskbar: sinon.stub().resolves(), unpinShortcutFromTaskbar: sinon.stub(), }; sinon.stub(ShellService, "shellService").value(kMockNativeShellService); sinon .stub(ShellService, "writeShortcutIcon") .callsFake(async (aIconFile, aImgContainer) => { if (gOverrideIconFileOnce) { await gWriteShortcutIcon(gOverrideIconFileOnce, aImgContainer); gOverrideIconFileOnce = null; } }); registerCleanupFunction(() => { sinon.restore(); }); // Favicons are written to the profile directory, ensure it exists. do_get_profile(); let gPngFavicon; let gSvgFavicon; add_setup(async () => { const pngFile = do_get_file("favicon-normal16.png"); const pngData = await IOUtils.read(pngFile.path); gPngFavicon = Services.io.newURI( `data:image/png;base64,${pngData.toBase64()}` ); const svgFile = do_get_file("icon.svg"); const svgData = await IOUtils.read(svgFile.path); gSvgFavicon = Services.io.newURI( `data:image/svg+xml;base64,${svgData.toBase64()}` ); }); async function testWrittenIconFile(aIconFile) { const data = await IOUtils.read(aIconFile.path); const imgContainer = imgTools.decodeImageFromArrayBuffer( data.buffer, ShellService.shortcutIconType.mimeType ); equal( imgContainer.width, 256, "Image written to disk should be 256px width." ); equal( imgContainer.height, 256, "Image written to disk should be 256px height." ); } const url = Services.io.newURI("https://www.test.com"); const userContextId = 0; const registry = new TaskbarTabsRegistry(); const taskbarTab = createTaskbarTab(registry, url, userContextId); const patchedSpy = sinon.stub(); registry.on(TaskbarTabsRegistry.events.patched, patchedSpy); function getTempFile() { let path = do_get_tempdir(); let filename = Services.uuid.generateUUID().toString().slice(1, -1); path.append(filename + "." + ShellService.shortcutIconType.extension); return path; } add_task(async function test_pin_saves_raster_icon() { sinon.resetHistory(); let iconFile = getTempFile(); gOverrideIconFileOnce = iconFile; let img = await TaskbarTabsUtils._imageFromLocalURI(gPngFavicon); await TaskbarTabsPin.pinTaskbarTab(taskbarTab, registry, img); equal( ShellService.writeShortcutIcon.firstCall.args[1], img, "The image that is saved should be the correct image" ); await testWrittenIconFile(iconFile); }); add_task(async function test_pin_saves_vector_icon() { sinon.resetHistory(); let iconFile = getTempFile(); gOverrideIconFileOnce = iconFile; let img = await TaskbarTabsUtils._imageFromLocalURI(gSvgFavicon); await TaskbarTabsPin.pinTaskbarTab(taskbarTab, registry, img); equal( ShellService.writeShortcutIcon.firstCall.args[1], img, "The image that is saved should be the correct image" ); await testWrittenIconFile(iconFile); });