diff --git a/browser/actors/ScreenshotsComponentChild.sys.mjs b/browser/actors/ScreenshotsComponentChild.sys.mjs index e8935356e157..8b6471ed8453 100644 --- a/browser/actors/ScreenshotsComponentChild.sys.mjs +++ b/browser/actors/ScreenshotsComponentChild.sys.mjs @@ -24,7 +24,7 @@ export class ScreenshotsComponentChild extends JSWindowActorChild { case "Screenshots:ShowOverlay": return this.startScreenshotsOverlay(); case "Screenshots:HideOverlay": - return this.endScreenshotsOverlay(message.data); + return this.endScreenshotsOverlay(); case "Screenshots:isOverlayShowing": return this.overlay?.initialized; case "Screenshots:getFullPageBounds": @@ -33,8 +33,6 @@ export class ScreenshotsComponentChild extends JSWindowActorChild { return this.getVisibleBounds(); case "Screenshots:getDocumentTitle": return this.getDocumentTitle(); - case "Screenshots:GetMethodsUsed": - return this.getMethodsUsed(); } return null; } @@ -117,7 +115,7 @@ export class ScreenshotsComponentChild extends JSWindowActorChild { requestCopyScreenshot(region) { region.devicePixelRatio = this.contentWindow.devicePixelRatio; this.sendAsyncMessage("Screenshots:CopyScreenshot", { region }); - this.endScreenshotsOverlay({ doNotResetMethods: true }); + this.endScreenshotsOverlay(); } /** @@ -130,7 +128,7 @@ export class ScreenshotsComponentChild extends JSWindowActorChild { title: this.getDocumentTitle(), region, }); - this.endScreenshotsOverlay({ doNotResetMethods: true }); + this.endScreenshotsOverlay(); } showPanel() { @@ -149,12 +147,6 @@ export class ScreenshotsComponentChild extends JSWindowActorChild { this.sendAsyncMessage("Screenshots:OverlaySelection", data); } - getMethodsUsed() { - let methodsUsed = this.#overlay.methodsUsed; - this.#overlay.resetMethodsUsed(); - return methodsUsed; - } - /** * Resolves when the document is ready to have an overlay injected into it. * @@ -220,13 +212,13 @@ export class ScreenshotsComponentChild extends JSWindowActorChild { /** * Removes event listeners and the screenshots overlay. */ - endScreenshotsOverlay(options = {}) { + endScreenshotsOverlay() { this.document.removeEventListener("keydown", this); this.document.ownerGlobal.removeEventListener("beforeunload", this); this.contentWindow.removeEventListener("resize", this); this.contentWindow.removeEventListener("scroll", this); this.contentWindow.removeEventListener("visibilitychange", this); - this.overlay?.tearDown(options); + this.overlay?.tearDown(); this.#resizeTask?.disarm(); this.#scrollTask?.disarm(); } diff --git a/browser/components/screenshots/ScreenshotsOverlayChild.sys.mjs b/browser/components/screenshots/ScreenshotsOverlayChild.sys.mjs index c992f275f57f..d6a27b072be2 100644 --- a/browser/components/screenshots/ScreenshotsOverlayChild.sys.mjs +++ b/browser/components/screenshots/ScreenshotsOverlayChild.sys.mjs @@ -44,7 +44,6 @@ const REGION_CHANGE_THRESHOLD = 5; const SCROLL_BY_EDGE = 20; export class ScreenshotsOverlay { - #content; #initialized = false; #state = ""; #moverId; @@ -54,7 +53,6 @@ export class ScreenshotsOverlay { #lastClientX; #lastClientY; #previousDimensions; - #methodsUsed; get markup() { let [cancel, instructions, download, copy] = @@ -146,10 +144,6 @@ export class ScreenshotsOverlay { return this.#state; } - get methodsUsed() { - return this.#methodsUsed; - } - constructor(contentDocument) { this.document = contentDocument; this.window = contentDocument.ownerGlobal; @@ -157,14 +151,13 @@ export class ScreenshotsOverlay { this.windowDimensions = new WindowDimensions(); this.selectionRegion = new Region(this.windowDimensions); this.hoverElementRegion = new Region(this.windowDimensions); - this.resetMethodsUsed(); } get content() { - if (!this.#content || Cu.isDeadWrapper(this.#content)) { + if (!this._content || Cu.isDeadWrapper(this._content)) { return null; } - return this.#content; + return this._content; } getElementById(id) { @@ -178,8 +171,8 @@ export class ScreenshotsOverlay { this.windowDimensions.reset(); - this.#content = this.document.insertAnonymousContent(); - this.#content.root.appendChild(this.fragment); + this._content = this.document.insertAnonymousContent(); + this._content.root.appendChild(this.fragment); this.initializeElements(); this.updateWindowDimensions(); @@ -221,21 +214,17 @@ export class ScreenshotsOverlay { /** * Removes all event listeners and removes the overlay from the Anonymous Content */ - tearDown(options = {}) { - if (this.#content) { + tearDown() { + if (this._content) { this.removeEventListeners(); - if (!(options.doNotResetMethods === true)) { - this.resetMethodsUsed(); - } try { - this.document.removeAnonymousContent(this.#content); + this.document.removeAnonymousContent(this._content); } catch (e) { // If the current window isn't the one the content was inserted into, this // will fail, but that's fine. } } this.#initialized = false; - this.#setState(""); } /** @@ -292,15 +281,6 @@ export class ScreenshotsOverlay { this.screenshotsContainer.removeEventListener("pointerup", this); } - resetMethodsUsed() { - this.#methodsUsed = { - element: 0, - region: 0, - move: 0, - resize: 0, - }; - } - /** * Returns the x and y coordinates of the event relative to both the * viewport and the page. @@ -762,7 +742,6 @@ export class ScreenshotsOverlay { eventName: "selected", reason: "element", }); - this.#methodsUsed.element += 1; } else { this.#setState("crosshairs"); } @@ -780,29 +759,7 @@ export class ScreenshotsOverlay { }; this.selectionRegion.sortCoords(); this.#setState("selected"); - this.maybeRecordRegionSelected(); - this.#methodsUsed.region += 1; - } - /** - * Update the selection region dimensions by calling `resizingDrag` and set - * the state to selected. - * @param {Number} pageX The x position relative to the page - * @param {Number} pageY The y position relative to the page - */ - resizingDragEnd(pageX, pageY, targetId) { - this.resizingDrag(pageX, pageY, targetId); - this.selectionRegion.sortCoords(); - this.#setState("selected"); - this.maybeRecordRegionSelected(); - if (targetId === "highlight") { - this.#methodsUsed.move += 1; - } else { - this.#methodsUsed.resize += 1; - } - } - - maybeRecordRegionSelected() { let { width, height } = this.selectionRegion.dimensions; if ( @@ -820,6 +777,18 @@ export class ScreenshotsOverlay { this.#previousDimensions = { width, height }; } + /** + * Update the selection region dimensions by calling `resizingDrag` and set + * the state to selected. + * @param {Number} pageX The x position relative to the page + * @param {Number} pageY The y position relative to the page + */ + resizingDragEnd(pageX, pageY, targetId) { + this.resizingDrag(pageX, pageY, targetId); + this.selectionRegion.sortCoords(); + this.#setState("selected"); + } + /** * Draw the preview eyes pointer towards the mouse. * @param {Number} clientX The x position relative to the viewport diff --git a/browser/components/screenshots/ScreenshotsUtils.sys.mjs b/browser/components/screenshots/ScreenshotsUtils.sys.mjs index e8c561615989..13c20edb5ce3 100644 --- a/browser/components/screenshots/ScreenshotsUtils.sys.mjs +++ b/browser/components/screenshots/ScreenshotsUtils.sys.mjs @@ -89,7 +89,6 @@ export const UIPhases = { export var ScreenshotsUtils = { browserToScreenshotsState: new WeakMap(), initialized: false, - methodsUsed: {}, /** * Figures out which of various states the screenshots UI is in, for the given browser. @@ -111,10 +110,6 @@ export var ScreenshotsUtils = { return UIPhases.CLOSED; }, - resetMethodsUsed() { - this.methodsUsed = { fullpage: 0, visible: 0 }; - }, - initialize() { if (!this.initialized) { if ( @@ -125,9 +120,9 @@ export var ScreenshotsUtils = { ) { return; } - this.resetMethodsUsed(); Services.telemetry.setEventRecordingEnabled("screenshots", true); Services.obs.addObserver(this, "menuitem-screenshot"); + Services.obs.addObserver(this, "screenshots-take-screenshot"); this.initialized = true; if (Cu.isInAutomation) { Services.obs.notifyObservers(null, "screenshots-component-initialized"); @@ -138,6 +133,7 @@ export var ScreenshotsUtils = { uninitialize() { if (this.initialized) { Services.obs.removeObserver(this, "menuitem-screenshot"); + Services.obs.removeObserver(this, "screenshots-take-screenshot"); this.initialized = false; } }, @@ -165,6 +161,16 @@ export var ScreenshotsUtils = { this.start(browser, data); break; } + case "screenshots-take-screenshot": { + this.closePanel(browser); + this.closeOverlay(browser); + + // init UI as a tab dialog box + this.openPreviewDialog(browser).then(dialog => { + this.doScreenshot(browser, dialog, data); + }); + break; + } } }, @@ -228,7 +234,6 @@ export var ScreenshotsUtils = { this.closeDialogBox(browser); this.closePanel(browser); this.closeOverlay(browser); - this.resetMethodsUsed(); this.browserToScreenshotsState.delete(browser); if (Cu.isInAutomation) { Services.obs.notifyObservers(null, "screenshots-exit"); @@ -385,9 +390,9 @@ export var ScreenshotsUtils = { * The overlay lives in the child document; so although closing is actually async, we assume success. * @param browser The current browser. */ - closeOverlay(browser, options = {}) { + closeOverlay(browser) { let actor = this.getActor(browser); - actor?.sendAsyncMessage("Screenshots:HideOverlay", options); + actor?.sendAsyncMessage("Screenshots:HideOverlay"); if (this.browserToScreenshotsState.has(browser)) { this.setPerBrowserState(browser, { @@ -555,27 +560,23 @@ export var ScreenshotsUtils = { }, /** - * Open and add screenshot-ui to the dialog box and then take the screenshot + * Add screenshot-ui to the dialog box and then take the screenshot * @param browser The current browser. + * @param dialog The dialog box to show the screenshot preview. * @param type The type of screenshot taken. */ - async doScreenshot(browser, type) { - this.closePanel(browser); - this.closeOverlay(browser, { doNotResetMethods: true }); - - let dialog = await this.openPreviewDialog(browser); + async doScreenshot(browser, dialog, type) { await dialog._dialogReady; let screenshotsUI = dialog._frame.contentDocument.createElement("screenshots-ui"); dialog._frame.contentDocument.body.appendChild(screenshotsUI); let rect; - if (type === "full_page") { + if (type === "full-page") { rect = await this.fetchFullPageBounds(browser); - this.methodsUsed.fullpage += 1; + type = "full_page"; } else { rect = await this.fetchVisibleBounds(browser); - this.methodsUsed.visible += 1; } this.recordTelemetryEvent("selected", type, {}); return this.takeScreenshot(browser, dialog, rect); @@ -677,19 +678,17 @@ export var ScreenshotsUtils = { let canvas = await this.createCanvas(region, browser); let url = canvas.toDataURL(); - await this.copyScreenshot(url, browser, { - object: "overlay_copy", - }); + this.copyScreenshot(url, browser); + + this.recordTelemetryEvent("copy", "overlay_copy", {}); }, /** * Copy the image to the clipboard - * This is called from the preview dialog * @param dataUrl The image data * @param browser The current browser - * @param data Telemetry data */ - async copyScreenshot(dataUrl, browser, data) { + copyScreenshot(dataUrl, browser) { // Guard against missing image data. if (!dataUrl) { return; @@ -722,15 +721,6 @@ export var ScreenshotsUtils = { ); this.showCopiedConfirmationHint(browser); - - let extra = await this.getActor(browser).sendQuery( - "Screenshots:GetMethodsUsed" - ); - this.recordTelemetryEvent("copy", data.object, { - ...extra, - ...this.methodsUsed, - }); - this.resetMethodsUsed(); }, /** @@ -743,20 +733,18 @@ export var ScreenshotsUtils = { let canvas = await this.createCanvas(region, browser); let dataUrl = canvas.toDataURL(); - await this.downloadScreenshot(title, dataUrl, browser, { - object: "overlay_download", - }); + await this.downloadScreenshot(title, dataUrl, browser); + + this.recordTelemetryEvent("download", "overlay_download", {}); }, /** * Download the screenshot - * This is called from the preview dialog * @param title The title of the current page or null and getFilename will get the title * @param dataUrl The image data * @param browser The current browser - * @param data Telemetry data */ - async downloadScreenshot(title, dataUrl, browser, data) { + async downloadScreenshot(title, dataUrl, browser) { // Guard against missing image data. if (!dataUrl) { return; @@ -785,23 +773,9 @@ export var ScreenshotsUtils = { // Await successful completion of the save via the download manager await download.start(); } catch (ex) {} - - let extra = await this.getActor(browser).sendQuery( - "Screenshots:GetMethodsUsed" - ); - this.recordTelemetryEvent("download", data.object, { - ...extra, - ...this.methodsUsed, - }); - this.resetMethodsUsed(); }, recordTelemetryEvent(type, object, args) { - if (args) { - for (let key of Object.keys(args)) { - args[key] = args[key].toString(); - } - } Services.telemetry.recordEvent("screenshots", type, object, null, args); }, }; diff --git a/browser/components/screenshots/content/screenshots.js b/browser/components/screenshots/content/screenshots.js index 678d1e95b1eb..476778e336b3 100644 --- a/browser/components/screenshots/content/screenshots.js +++ b/browser/components/screenshots/content/screenshots.js @@ -6,6 +6,8 @@ "use strict"; ChromeUtils.defineESModuleGetters(this, { + Downloads: "resource://gre/modules/Downloads.sys.mjs", + FileUtils: "resource://gre/modules/FileUtils.sys.mjs", ScreenshotsUtils: "resource:///modules/ScreenshotsUtils.sys.mjs", }); @@ -76,16 +78,15 @@ class ScreenshotsUI extends HTMLElement { await ScreenshotsUtils.downloadScreenshot( null, dataUrl, - this.openerBrowser, - { object: "preview_download" } + this.openerBrowser ); + ScreenshotsUtils.recordTelemetryEvent("download", "preview_download", {}); this.close(); } - async saveToClipboard(dataUrl) { - await ScreenshotsUtils.copyScreenshot(dataUrl, this.openerBrowser, { - object: "preview_copy", - }); + saveToClipboard(dataUrl) { + ScreenshotsUtils.copyScreenshot(dataUrl, this.openerBrowser); + ScreenshotsUtils.recordTelemetryEvent("copy", "preview_copy", {}); this.close(); } } diff --git a/browser/components/screenshots/screenshots-buttons.js b/browser/components/screenshots/screenshots-buttons.js index b69d78a4337f..528bf6ab1d87 100644 --- a/browser/components/screenshots/screenshots-buttons.js +++ b/browser/components/screenshots/screenshots-buttons.js @@ -8,10 +8,6 @@ // This is loaded into chrome windows with the subscript loader. Wrap in // a block to prevent accidentally leaking globals onto `window`. { - ChromeUtils.defineESModuleGetters(this, { - ScreenshotsUtils: "resource:///modules/ScreenshotsUtils.sys.mjs", - }); - class ScreenshotsButtons extends MozXULElement { static get markup() { return ` @@ -29,14 +25,22 @@ let fragment = MozXULElement.parseXULToFragment(this.constructor.markup); this.shadowRoot.append(fragment); - let visibleButton = shadowRoot.querySelector(".visible-page"); - visibleButton.onclick = function () { - ScreenshotsUtils.doScreenshot(gBrowser.selectedBrowser, "visible"); + let button1 = shadowRoot.querySelector(".visible-page"); + button1.onclick = function () { + Services.obs.notifyObservers( + gBrowser.ownerGlobal, + "screenshots-take-screenshot", + "visible" + ); }; - let fullpageButton = shadowRoot.querySelector(".full-page"); - fullpageButton.onclick = function () { - ScreenshotsUtils.doScreenshot(gBrowser.selectedBrowser, "full_page"); + let button2 = shadowRoot.querySelector(".full-page"); + button2.onclick = function () { + Services.obs.notifyObservers( + gBrowser.ownerGlobal, + "screenshots-take-screenshot", + "full-page" + ); }; } diff --git a/browser/components/screenshots/tests/browser/browser_screenshots_drag_test.js b/browser/components/screenshots/tests/browser/browser_screenshots_drag_test.js index fb938fd48e89..a8c05dcb499c 100644 --- a/browser/components/screenshots/tests/browser/browser_screenshots_drag_test.js +++ b/browser/components/screenshots/tests/browser/browser_screenshots_drag_test.js @@ -16,9 +16,6 @@ add_task(async function dragTest() { let helper = new ScreenshotsHelper(browser); let contentInfo = await helper.getContentDimensions(); ok(contentInfo, "Got dimensions back from the content"); - let expected = Math.floor( - 490 * (await getContentDevicePixelRatio(browser)) - ); helper.triggerUIFromToolbar(); @@ -26,18 +23,21 @@ add_task(async function dragTest() { await helper.dragOverlay(10, 10, 500, 500); - let clipboardChanged = helper.waitForRawClipboardChange( - expected, - expected - ); + let clipboardChanged = helper.waitForRawClipboardChange(); - await helper.clickCopyButton(); + helper.clickCopyButton(); info("Waiting for clipboard change"); - let result = await clipboardChanged; + await clipboardChanged; + + let result = await helper.getImageSizeAndColorFromClipboard(); info("result: " + JSON.stringify(result, null, 2)); + let expected = Math.floor( + 490 * (await getContentDevicePixelRatio(browser)) + ); + Assert.equal( result.width, expected, @@ -68,9 +68,6 @@ add_task(async function dragTest1Point5Zoom() { let contentInfo = await helper.getContentDimensions(); ok(contentInfo, "Got dimensions back from the content"); - let expected = Math.floor( - 50 * (await getContentDevicePixelRatio(browser)) - ); helper.triggerUIFromToolbar(); @@ -78,16 +75,14 @@ add_task(async function dragTest1Point5Zoom() { await helper.dragOverlay(300, 100, 350, 150); - let clipboardChanged = helper.waitForRawClipboardChange( - expected, - expected - ); + let clipboardChanged = helper.waitForRawClipboardChange(); - await helper.clickCopyButton(); + helper.clickCopyButton(); info("Waiting for clipboard change"); - let result = await clipboardChanged; + await clipboardChanged; + let result = await helper.getImageSizeAndColorFromClipboard(); result.zoom = zoom; result.devicePixelRatio = window.devicePixelRatio; result.contentDevicePixelRatio = await getContentDevicePixelRatio( @@ -96,6 +91,10 @@ add_task(async function dragTest1Point5Zoom() { info("result: " + JSON.stringify(result, null, 2)); + let expected = Math.floor( + 50 * (await getContentDevicePixelRatio(browser)) + ); + Assert.equal( result.width, expected, @@ -164,7 +163,7 @@ add_task(async function overlayCancelButton() { await helper.dragOverlay(10, 10, 300, 300); - await helper.clickCancelButton(); + helper.clickCancelButton(); await helper.waitForOverlayClosed(); @@ -188,9 +187,6 @@ add_task(async function preserveBoxSizeWhenMovingOutOfWindowBounds() { let contentInfo = await helper.getContentDimensions(); ok(contentInfo, "Got dimensions back from the content"); - let expected = Math.floor( - 490 * (await getContentDevicePixelRatio(browser)) - ); helper.triggerUIFromToolbar(); @@ -221,18 +217,21 @@ add_task(async function preserveBoxSizeWhenMovingOutOfWindowBounds() { Math.floor((endY - startY) / 2) ); - let clipboardChanged = helper.waitForRawClipboardChange( - expected, - expected - ); + let clipboardChanged = helper.waitForRawClipboardChange(); - await helper.clickCopyButton(); + helper.clickCopyButton(); info("Waiting for clipboard change"); - let result = await clipboardChanged; + await clipboardChanged; + + let result = await helper.getImageSizeAndColorFromClipboard(); info("result: " + JSON.stringify(result, null, 2)); + let expected = Math.floor( + 490 * (await getContentDevicePixelRatio(browser)) + ); + Assert.equal( result.width, expected, @@ -262,9 +261,6 @@ add_task(async function resizeAllEdges() { let contentInfo = await helper.getContentDimensions(); ok(contentInfo, "Got dimensions back from the content"); - let expected = Math.floor( - 300 * (await getContentDevicePixelRatio(browser)) - ); helper.triggerUIFromToolbar(); @@ -336,21 +332,24 @@ add_task(async function resizeAllEdges() { state = await helper.getOverlayState(); Assert.equal(state, "selected", "The overlay is in the selected state"); - let clipboardChanged = helper.waitForRawClipboardChange( - expected, - expected - ); + let clipboardChanged = helper.waitForRawClipboardChange(); helper.endX = 400; helper.endY = 400; - await helper.clickCopyButton(); + helper.clickCopyButton(); info("Waiting for clipboard change"); - let result = await clipboardChanged; + await clipboardChanged; + + let result = await helper.getImageSizeAndColorFromClipboard(); info("result: " + JSON.stringify(result, null, 2)); + let expected = Math.floor( + 300 * (await getContentDevicePixelRatio(browser)) + ); + Assert.equal( result.width, expected, @@ -380,9 +379,6 @@ add_task(async function resizeAllCorners() { let contentInfo = await helper.getContentDimensions(); ok(contentInfo, "Got dimensions back from the content"); - let expected = Math.floor( - 300 * (await getContentDevicePixelRatio(browser)) - ); helper.triggerUIFromToolbar(); @@ -446,21 +442,24 @@ add_task(async function resizeAllCorners() { state = await helper.getOverlayState(); Assert.equal(state, "selected", "The overlay is in the selected state"); - let clipboardChanged = helper.waitForRawClipboardChange( - expected, - expected - ); + let clipboardChanged = helper.waitForRawClipboardChange(); helper.endX = 400; helper.endY = 400; - await helper.clickCopyButton(); + helper.clickCopyButton(); info("Waiting for clipboard change"); - let result = await clipboardChanged; + await clipboardChanged; + + let result = await helper.getImageSizeAndColorFromClipboard(); info("result: " + JSON.stringify(result, null, 2)); + let expected = Math.floor( + 300 * (await getContentDevicePixelRatio(browser)) + ); + Assert.equal( result.width, expected, diff --git a/browser/components/screenshots/tests/browser/browser_screenshots_telemetry_tests.js b/browser/components/screenshots/tests/browser/browser_screenshots_telemetry_tests.js index 757756b15a3e..64030a5d6e60 100644 --- a/browser/components/screenshots/tests/browser/browser_screenshots_telemetry_tests.js +++ b/browser/components/screenshots/tests/browser/browser_screenshots_telemetry_tests.js @@ -37,49 +37,11 @@ const COPY_EVENTS = [ ]; const CONTENT_EVENTS = [ - { category: "screenshots", method: "selected", object: "region_selection" }, { category: "screenshots", method: "selected", object: "region_selection" }, { category: "screenshots", method: "started", object: "overlay_retry" }, { category: "screenshots", method: "selected", object: "element" }, ]; -const EXTRA_OVERLAY_EVENTS = [ - { category: "screenshots", method: "started", object: "toolbar_button" }, - { - category: "screenshots", - method: "copy", - object: "overlay_copy", - extra: { - element: "1", - region: "1", - move: "1", - resize: "1", - fullpage: "0", - visible: "0", - }, - }, -]; - -const EXTRA_EVENTS = [ - { category: "screenshots", method: "started", object: "toolbar_button" }, - { category: "screenshots", method: "selected", object: "visible" }, - { category: "screenshots", method: "started", object: "preview_retry" }, - { category: "screenshots", method: "selected", object: "full_page" }, - { - category: "screenshots", - method: "copy", - object: "preview_copy", - extra: { - element: "0", - region: "0", - move: "0", - resize: "0", - fullpage: "1", - visible: "1", - }, - }, -]; - add_task(async function test_started_and_canceled_events() { await SpecialPowers.pushPrefEnv({ set: [ @@ -272,7 +234,7 @@ add_task(async function test_canceled() { await helper.dragOverlay(50, 50, 300, 300); screenshotExit = TestUtils.topicObserved("screenshots-exit"); - await helper.clickCancelButton(); + helper.clickCancelButton(); await helper.waitForOverlayClosed(); await screenshotExit; @@ -291,16 +253,6 @@ add_task(async function test_copy() { async browser => { await clearAllTelemetryEvents(); let helper = new ScreenshotsHelper(browser); - let contentInfo = await helper.getContentDimensions(); - ok(contentInfo, "Got dimensions back from the content"); - let devicePixelRatio = await getContentDevicePixelRatio(browser); - - let expectedWidth = Math.floor( - devicePixelRatio * contentInfo.clientWidth - ); - let expectedHeight = Math.floor( - devicePixelRatio * contentInfo.clientHeight - ); helper.triggerUIFromToolbar(); info("waiting for overlay"); @@ -325,10 +277,7 @@ add_task(async function test_copy() { let copyButton = dialog._frame.contentDocument.getElementById("copy"); let screenshotExit = TestUtils.topicObserved("screenshots-exit"); - let clipboardChanged = helper.waitForRawClipboardChange( - expectedWidth, - expectedHeight - ); + let clipboardChanged = helper.waitForRawClipboardChange(); // click copy button on dialog box info("clicking the copy button"); @@ -345,13 +294,10 @@ add_task(async function test_copy() { await helper.dragOverlay(50, 50, 300, 300); - clipboardChanged = helper.waitForRawClipboardChange( - devicePixelRatio * 250, - devicePixelRatio * 250 - ); + clipboardChanged = helper.waitForRawClipboardChange(); screenshotExit = TestUtils.topicObserved("screenshots-exit"); - await helper.clickCopyButton(); + helper.clickCopyButton(); info("Waiting for clipboard change"); await clipboardChanged; @@ -379,89 +325,12 @@ add_task(async function test_content_events() { await helper.dragOverlay(50, 50, 300, 300); - await helper.dragOverlay(300, 300, 333, 333, "selected"); - - await helper.dragOverlay(150, 150, 200, 200, "selected"); - mouse.click(11, 11); await helper.waitForStateChange("crosshairs"); await helper.clickTestPageElement(); - let screenshotExit = TestUtils.topicObserved("screenshots-exit"); - - await helper.clickCopyButton(); - - info("Waiting for exit"); - await screenshotExit; - - await assertScreenshotsEvents(CONTENT_EVENTS, "content", false); - await assertScreenshotsEvents(EXTRA_OVERLAY_EVENTS); - } - ); -}); - -add_task(async function test_extra_telemetry() { - await BrowserTestUtils.withNewTab( - { - gBrowser, - url: TEST_PAGE, - }, - async browser => { - await clearAllTelemetryEvents(); - let helper = new ScreenshotsHelper(browser); - let contentInfo = await helper.getContentDimensions(); - ok(contentInfo, "Got dimensions back from the content"); - - helper.triggerUIFromToolbar(); - info("waiting for overlay"); - await helper.waitForOverlay(); - - info("waiting for panel"); - let panel = await helper.waitForPanel(); - - let screenshotReady = TestUtils.topicObserved( - "screenshots-preview-ready" - ); - - // click the visible page button in panel - let visiblePageButton = panel - .querySelector("screenshots-buttons") - .shadowRoot.querySelector(".visible-page"); - visiblePageButton.click(); - info("clicked visible page, waiting for screenshots-preview-ready"); - await screenshotReady; - - let dialog = helper.getDialog(); - let retryButton = dialog._frame.contentDocument.getElementById("retry"); - retryButton.click(); - - info("waiting for panel"); - panel = await helper.waitForPanel(); - - screenshotReady = TestUtils.topicObserved("screenshots-preview-ready"); - - // click the full page button in panel - let fullPageButton = panel - .querySelector("screenshots-buttons") - .shadowRoot.querySelector(".full-page"); - fullPageButton.click(); - await screenshotReady; - - let screenshotExit = TestUtils.topicObserved("screenshots-exit"); - - dialog = helper.getDialog(); - let copyButton = dialog._frame.contentDocument.getElementById("copy"); - retryButton.click(); - // click copy button on dialog box - info("clicking the copy button"); - copyButton.click(); - - info("waiting for screenshot exit"); - await screenshotExit; - - info("Waiting for assertScreenshotsEvents"); - await assertScreenshotsEvents(EXTRA_EVENTS); + await assertScreenshotsEvents(CONTENT_EVENTS, "content"); } ); }); diff --git a/browser/components/screenshots/tests/browser/browser_screenshots_test_downloads.js b/browser/components/screenshots/tests/browser/browser_screenshots_test_downloads.js index 770a7ae06b12..ac8c9e45439c 100644 --- a/browser/components/screenshots/tests/browser/browser_screenshots_test_downloads.js +++ b/browser/components/screenshots/tests/browser/browser_screenshots_test_downloads.js @@ -84,7 +84,7 @@ add_task(async function test_download_without_filepicker() { await helper.waitForOverlay(); await helper.dragOverlay(10, 10, 500, 500); - await helper.clickDownloadButton(); + helper.clickDownloadButton(); info("wait for download to finish"); let download = await downloadFinishedPromise; @@ -170,7 +170,7 @@ add_task(async function test_download_with_filepicker() { let filePicker = waitForFilePicker(); let screenshotExit = TestUtils.topicObserved("screenshots-exit"); - await helper.clickDownloadButton(); + helper.clickDownloadButton(); await filePicker; ok(true, "Export file picker opened"); diff --git a/browser/components/screenshots/tests/browser/browser_screenshots_test_full_page.js b/browser/components/screenshots/tests/browser/browser_screenshots_test_full_page.js index 51cda963d9fa..c66b4c77d9b2 100644 --- a/browser/components/screenshots/tests/browser/browser_screenshots_test_full_page.js +++ b/browser/components/screenshots/tests/browser/browser_screenshots_test_full_page.js @@ -17,14 +17,6 @@ add_task(async function test_fullpageScreenshot() { let helper = new ScreenshotsHelper(browser); let contentInfo = await helper.getContentDimensions(); ok(contentInfo, "Got dimensions back from the content"); - let devicePixelRatio = await getContentDevicePixelRatio(browser); - - let expectedWidth = Math.floor( - devicePixelRatio * contentInfo.scrollWidth - ); - let expectedHeight = Math.floor( - devicePixelRatio * contentInfo.scrollHeight - ); // click toolbar button so panel shows helper.triggerUIFromToolbar(); @@ -48,22 +40,29 @@ add_task(async function test_fullpageScreenshot() { let copyButton = dialog._frame.contentDocument.getElementById("copy"); ok(copyButton, "Got the copy button"); - let clipboardChanged = helper.waitForRawClipboardChange( - expectedWidth, - expectedHeight - ); + let clipboardChanged = helper.waitForRawClipboardChange(); // click copy button on dialog box copyButton.click(); info("Waiting for clipboard change"); - let result = await clipboardChanged; + await clipboardChanged; + let result = await helper.getImageSizeAndColorFromClipboard(); info("result: " + JSON.stringify(result, null, 2)); info("contentInfo: " + JSON.stringify(contentInfo, null, 2)); - Assert.equal(result.width, expectedWidth, "Widths should be equal"); - Assert.equal(result.height, expectedHeight, "Heights should be equal"); + Assert.equal( + contentInfo.scrollWidth, + result.width, + "Widths should be equal" + ); + + Assert.equal( + contentInfo.scrollHeight, + result.height, + "Heights should be equal" + ); // top left assertRange(result.color.topLeft[0], 110, 111, "R color value"); @@ -102,14 +101,6 @@ add_task(async function test_fullpageScreenshotScrolled() { }); let contentInfo = await helper.getContentDimensions(); ok(contentInfo, "Got dimensions back from the content"); - let devicePixelRatio = await getContentDevicePixelRatio(browser); - - let expectedWidth = Math.floor( - devicePixelRatio * contentInfo.scrollWidth - ); - let expectedHeight = Math.floor( - devicePixelRatio * contentInfo.scrollHeight - ); // click toolbar button so panel shows helper.triggerUIFromToolbar(); @@ -134,22 +125,29 @@ add_task(async function test_fullpageScreenshotScrolled() { let copyButton = dialog._frame.contentDocument.getElementById("copy"); ok(copyButton, "Got the copy button"); - let clipboardChanged = helper.waitForRawClipboardChange( - expectedWidth, - expectedHeight - ); + let clipboardChanged = helper.waitForRawClipboardChange(); // click copy button on dialog box copyButton.click(); info("Waiting for clipboard change"); - let result = await clipboardChanged; + await clipboardChanged; + let result = await helper.getImageSizeAndColorFromClipboard(); info("result: " + JSON.stringify(result, null, 2)); info("contentInfo: " + JSON.stringify(contentInfo, null, 2)); - Assert.equal(result.width, expectedWidth, "Widths should be equal"); - Assert.equal(result.height, expectedHeight, "Heights should be equal"); + Assert.equal( + contentInfo.scrollWidth, + result.width, + "Widths should be equal" + ); + + Assert.equal( + contentInfo.scrollHeight, + result.height, + "Heights should be equal" + ); // top left assertRange(result.color.topLeft[0], 110, 111, "R color value"); diff --git a/browser/components/screenshots/tests/browser/browser_screenshots_test_visible.js b/browser/components/screenshots/tests/browser/browser_screenshots_test_visible.js index 7b7a46f73ddb..26d28566c8c5 100644 --- a/browser/components/screenshots/tests/browser/browser_screenshots_test_visible.js +++ b/browser/components/screenshots/tests/browser/browser_screenshots_test_visible.js @@ -15,13 +15,6 @@ add_task(async function test_visibleScreenshot() { ok(contentInfo, "Got dimensions back from the content"); let devicePixelRatio = await getContentDevicePixelRatio(browser); - let expectedWidth = Math.floor( - devicePixelRatio * contentInfo.clientWidth - ); - let expectedHeight = Math.floor( - devicePixelRatio * contentInfo.clientHeight - ); - // click toolbar button so panel shows helper.triggerUIFromToolbar(); @@ -48,21 +41,26 @@ add_task(async function test_visibleScreenshot() { let copyButton = dialog._frame.contentDocument.getElementById("copy"); ok(copyButton, "Got the copy button"); - let clipboardChanged = helper.waitForRawClipboardChange( - expectedWidth, - expectedHeight - ); + let clipboardChanged = helper.waitForRawClipboardChange(); // click copy button on dialog box copyButton.click(); info("Waiting for clipboard change"); - let result = await clipboardChanged; + await clipboardChanged; + let result = await helper.getImageSizeAndColorFromClipboard(); info("result: " + JSON.stringify(result, null, 2)); info("contentInfo: " + JSON.stringify(contentInfo, null, 2)); + let expectedWidth = Math.floor( + devicePixelRatio * contentInfo.clientWidth + ); Assert.equal(result.width, expectedWidth, "Widths should be equal"); + + let expectedHeight = Math.floor( + devicePixelRatio * contentInfo.clientHeight + ); Assert.equal(result.height, expectedHeight, "Heights should be equal"); // top left @@ -88,7 +86,7 @@ add_task(async function test_visibleScreenshot() { ); }); -add_task(async function test_visibleScreenshotScrolledY() { +add_task(async function test_visibleScreenshotScrolled() { await BrowserTestUtils.withNewTab( { gBrowser, @@ -102,14 +100,6 @@ add_task(async function test_visibleScreenshotScrolledY() { let helper = new ScreenshotsHelper(browser); let contentInfo = await helper.getContentDimensions(); ok(contentInfo, "Got dimensions back from the content"); - let devicePixelRatio = await getContentDevicePixelRatio(browser); - - let expectedWidth = Math.floor( - devicePixelRatio * contentInfo.clientWidth - ); - let expectedHeight = Math.floor( - devicePixelRatio * contentInfo.clientHeight - ); // click toolbar button so panel shows helper.triggerUIFromToolbar(); @@ -136,24 +126,27 @@ add_task(async function test_visibleScreenshotScrolledY() { let copyButton = dialog._frame.contentDocument.getElementById("copy"); ok(copyButton, "Got the copy button"); - let clipboardChanged = helper.waitForRawClipboardChange( - expectedWidth, - expectedHeight - ); + let clipboardChanged = helper.waitForRawClipboardChange(); // click copy button on dialog box copyButton.click(); info("Waiting for clipboard change"); - let result = await clipboardChanged; + await clipboardChanged; - // let result = await helper.getImageSizeAndColorFromClipboard(); - // debugger; + let result = await helper.getImageSizeAndColorFromClipboard(); info("result: " + JSON.stringify(result, null, 2)); info("contentInfo: " + JSON.stringify(contentInfo, null, 2)); + let expectedWidth = Math.floor( + devicePixelRatio * contentInfo.clientWidth + ); Assert.equal(result.width, expectedWidth, "Widths should be equal"); + + let expectedHeight = Math.floor( + devicePixelRatio * contentInfo.clientHeight + ); Assert.equal(result.height, expectedHeight, "Heights should be equal"); // top left @@ -179,7 +172,7 @@ add_task(async function test_visibleScreenshotScrolledY() { ); }); -add_task(async function test_visibleScreenshotScrolledX() { +add_task(async function test_visibleScreenshotScrolled() { await BrowserTestUtils.withNewTab( { gBrowser, @@ -193,14 +186,6 @@ add_task(async function test_visibleScreenshotScrolledX() { let helper = new ScreenshotsHelper(browser); let contentInfo = await helper.getContentDimensions(); ok(contentInfo, "Got dimensions back from the content"); - let devicePixelRatio = await getContentDevicePixelRatio(browser); - - let expectedWidth = Math.floor( - devicePixelRatio * contentInfo.clientWidth - ); - let expectedHeight = Math.floor( - devicePixelRatio * contentInfo.clientHeight - ); // click toolbar button so panel shows helper.triggerUIFromToolbar(); @@ -227,21 +212,27 @@ add_task(async function test_visibleScreenshotScrolledX() { let copyButton = dialog._frame.contentDocument.getElementById("copy"); ok(copyButton, "Got the copy button"); - let clipboardChanged = helper.waitForRawClipboardChange( - expectedWidth, - expectedHeight - ); + let clipboardChanged = helper.waitForRawClipboardChange(); // click copy button on dialog box copyButton.click(); info("Waiting for clipboard change"); - let result = await clipboardChanged; + await clipboardChanged; + + let result = await helper.getImageSizeAndColorFromClipboard(); info("result: " + JSON.stringify(result, null, 2)); info("contentInfo: " + JSON.stringify(contentInfo, null, 2)); + let expectedWidth = Math.floor( + devicePixelRatio * contentInfo.clientWidth + ); Assert.equal(result.width, expectedWidth, "Widths should be equal"); + + let expectedHeight = Math.floor( + devicePixelRatio * contentInfo.clientHeight + ); Assert.equal(result.height, expectedHeight, "Heights should be equal"); // top left @@ -267,7 +258,7 @@ add_task(async function test_visibleScreenshotScrolledX() { ); }); -add_task(async function test_visibleScreenshotScrolledXAndY() { +add_task(async function test_visibleScreenshotScrolled() { await BrowserTestUtils.withNewTab( { gBrowser, @@ -281,14 +272,6 @@ add_task(async function test_visibleScreenshotScrolledXAndY() { let helper = new ScreenshotsHelper(browser); let contentInfo = await helper.getContentDimensions(); ok(contentInfo, "Got dimensions back from the content"); - let devicePixelRatio = await getContentDevicePixelRatio(browser); - - let expectedWidth = Math.floor( - devicePixelRatio * contentInfo.clientWidth - ); - let expectedHeight = Math.floor( - devicePixelRatio * contentInfo.clientHeight - ); // click toolbar button so panel shows helper.triggerUIFromToolbar(); @@ -315,21 +298,27 @@ add_task(async function test_visibleScreenshotScrolledXAndY() { let copyButton = dialog._frame.contentDocument.getElementById("copy"); ok(copyButton, "Got the copy button"); - let clipboardChanged = helper.waitForRawClipboardChange( - expectedWidth, - expectedHeight - ); + let clipboardChanged = helper.waitForRawClipboardChange(); // click copy button on dialog box copyButton.click(); info("Waiting for clipboard change"); - let result = await clipboardChanged; + await clipboardChanged; + + let result = await helper.getImageSizeAndColorFromClipboard(); info("result: " + JSON.stringify(result, null, 2)); info("contentInfo: " + JSON.stringify(contentInfo, null, 2)); + let expectedWidth = Math.floor( + devicePixelRatio * contentInfo.clientWidth + ); Assert.equal(result.width, expectedWidth, "Widths should be equal"); + + let expectedHeight = Math.floor( + devicePixelRatio * contentInfo.clientHeight + ); Assert.equal(result.height, expectedHeight, "Heights should be equal"); // top left diff --git a/browser/components/screenshots/tests/browser/head.js b/browser/components/screenshots/tests/browser/head.js index c7a0fa14de7a..352be063ce0c 100644 --- a/browser/components/screenshots/tests/browser/head.js +++ b/browser/components/screenshots/tests/browser/head.js @@ -143,7 +143,7 @@ class ScreenshotsHelper { } async waitForStateChange(newState) { - return BrowserTestUtils.waitForCondition(async () => { + await BrowserTestUtils.waitForCondition(async () => { let state = await this.getOverlayState(); return state === newState; }, `Waiting for state change to ${newState}`); @@ -204,36 +204,26 @@ class ScreenshotsHelper { * @param {Number} endX The end X coordinate. The right edge of the overlay rect. * @param {Number} endY The end Y coordinate. The bottom edge of the overlay rect. */ - async dragOverlay( - startX, - startY, - endX, - endY, - expectedStartingState = "crosshairs" - ) { - await this.waitForStateChange(expectedStartingState); + async dragOverlay(startX, startY, endX, endY) { + await this.waitForStateChange("crosshairs"); let state = await this.getOverlayState(); - Assert.equal( - state, - expectedStartingState, - `The overlay is in the ${state} state` - ); + Assert.equal(state, "crosshairs", "The overlay is in the crosshairs state"); mouse.down(startX, startY); - await Promise.any([ - this.waitForStateChange("draggingReady"), - this.waitForStateChange("resizing"), - ]); - Assert.ok(true, "The overlay is in the draggingReady or resizing state"); + await this.waitForStateChange("draggingReady"); + state = await this.getOverlayState(); + Assert.equal( + state, + "draggingReady", + "The overlay is in the draggingReady state" + ); mouse.move(endX, endY); - await Promise.any([ - this.waitForStateChange("dragging"), - this.waitForStateChange("resizing"), - ]); - Assert.ok(true, "The overlay is in the dragging or resizing state"); + await this.waitForStateChange("dragging"); + state = await this.getOverlayState(); + Assert.equal(state, "dragging", "The overlay is in the dragging state"); mouse.up(endX, endY); @@ -281,64 +271,31 @@ class ScreenshotsHelper { }); } - async clickDownloadButton() { - let { centerX: x, centerY: y } = await ContentTask.spawn( - this.browser, - null, - async () => { - let screenshotsChild = content.windowGlobalChild.getActor( - "ScreenshotsComponent" - ); - let { left, top, width, height } = - screenshotsChild.overlay.downloadButton.getBoundingClientRect(); - let centerX = left + width / 2; - let centerY = top + height / 2; - return { centerX, centerY }; - } - ); - - info(`clicking download button at ${x}, ${y}`); - mouse.click(x, y); + clickDownloadButton() { + ContentTask.spawn(this.browser, null, async () => { + let screenshotsChild = content.windowGlobalChild.getActor( + "ScreenshotsComponent" + ); + screenshotsChild.overlay.downloadButton.click(); + }); } - async clickCopyButton() { - let { centerX: x, centerY: y } = await ContentTask.spawn( - this.browser, - null, - async () => { - let screenshotsChild = content.windowGlobalChild.getActor( - "ScreenshotsComponent" - ); - let { left, top, width, height } = - screenshotsChild.overlay.copyButton.getBoundingClientRect(); - let centerX = left + width / 2; - let centerY = top + height / 2; - return { centerX, centerY }; - } - ); - - info(`clicking copy button at ${x}, ${y}`); - mouse.click(x, y); + clickCopyButton() { + ContentTask.spawn(this.browser, null, async () => { + let screenshotsChild = content.windowGlobalChild.getActor( + "ScreenshotsComponent" + ); + screenshotsChild.overlay.copyButton.click(); + }); } - async clickCancelButton() { - let { centerX: x, centerY: y } = await ContentTask.spawn( - this.browser, - null, - async () => { - let screenshotsChild = content.windowGlobalChild.getActor( - "ScreenshotsComponent" - ); - let { left, top, width, height } = - screenshotsChild.overlay.cancelButton.getBoundingClientRect(); - let centerX = left + width / 2; - let centerY = top + height / 2; - return { centerX, centerY }; - } - ); - - info(`clicking cancel button at ${x}, ${y}`); - mouse.click(x, y); + clickCancelButton() { + ContentTask.spawn(this.browser, null, async () => { + let screenshotsChild = content.windowGlobalChild.getActor( + "ScreenshotsComponent" + ); + screenshotsChild.overlay.cancelButton.click(); + }); } async clickTestPageElement() { @@ -403,32 +360,21 @@ class ScreenshotsHelper { * Returns a promise that resolves when the clipboard data has changed * Otherwise rejects */ - waitForRawClipboardChange(epectedWidth, expectedHeight) { + waitForRawClipboardChange() { const initialClipboardData = Date.now().toString(); SpecialPowers.clipboardCopyString(initialClipboardData); - return TestUtils.waitForCondition( - async () => { - let data; - try { - data = await this.getImageSizeAndColorFromClipboard(); - } catch (e) { - console.log("Failed to get image/png clipboard data:", e); - return false; - } - if ( - data && - initialClipboardData !== data && - data.height === expectedHeight && - data.width === epectedWidth - ) { - return data; - } + let promiseChanged = TestUtils.waitForCondition(() => { + let data; + try { + data = getRawClipboardData("image/png"); + } catch (e) { + console.log("Failed to get image/png clipboard data:", e); return false; - }, - "Waiting for screenshot to copy to clipboard", - 200 - ); + } + return data && initialClipboardData !== data; + }); + return promiseChanged; } /** @@ -525,9 +471,7 @@ class ScreenshotsHelper { async getImageSizeAndColorFromClipboard() { let flavor = "image/png"; let image = getRawClipboardData(flavor); - if (!image) { - return false; - } + ok(image, "screenshot data exists on the clipboard"); // Due to the differences in how images could be stored in the clipboard the // checks below are needed. The clipboard could already provide the image as @@ -550,11 +494,10 @@ class ScreenshotsHelper { binaryStream.setInputStream(image); const available = binaryStream.available(); const buffer = new ArrayBuffer(available); - info( - `${binaryStream.readArrayBuffer( - available, - buffer - )} read, ${available} available` + is( + binaryStream.readArrayBuffer(available, buffer), + available, + "Read expected amount of data" ); // We are going to load the image in the content page to measure its size. @@ -707,18 +650,14 @@ async function waitForScreenshotsEventCount(count, process = "parent") { ); } -async function assertScreenshotsEvents( - expectedEvents, - process = "parent", - clearEvents = true -) { +async function assertScreenshotsEvents(expectedEvents, process = "parent") { info(`Expected events: ${JSON.stringify(expectedEvents, null, 2)}`); // Make sure we have recorded the correct number of events await waitForScreenshotsEventCount(expectedEvents.length, process); TelemetryTestUtils.assertEvents( expectedEvents, - { category: "screenshots" }, - { clear: clearEvents, process } + { category: "screenshots", clear: true }, + { process } ); } diff --git a/toolkit/components/telemetry/Events.yaml b/toolkit/components/telemetry/Events.yaml index db2221de1e4f..0269740c98eb 100644 --- a/toolkit/components/telemetry/Events.yaml +++ b/toolkit/components/telemetry/Events.yaml @@ -4225,13 +4225,6 @@ screenshots: - 1801019 expiry_version: "never" release_channel_collection: opt-out - extra_keys: - fullpage: Number of times a full page was selected - visible: Number of times a visible page was selected - element: Number of times an element was selected - region: Number of times a region was selected - move: Number of times a region was moved - resize: Number of times a region was resized copy: objects: ["overlay_copy", "preview_copy"] description: > @@ -4246,13 +4239,6 @@ screenshots: - 1801019 expiry_version: "never" release_channel_collection: opt-out - extra_keys: - fullpage: Number of times a full page was selected - visible: Number of times a visible page was selected - element: Number of times an element was selected - region: Number of times a region was selected - move: Number of times a region was moved - resize: Number of times a region was resized selected: objects: ["element", "region_selection", "visible", "full_page"] description: >