Skip to content

Commit

Permalink
Bug 1666247 - Part 1: Add a simplify page checkbox r=emalysz,flod
Browse files Browse the repository at this point in the history
mstriemer committed Jul 8, 2021
1 parent b17ce24 commit b8e7c50
Showing 21 changed files with 1,119 additions and 601 deletions.
9 changes: 5 additions & 4 deletions browser/base/content/browser.css
Original file line number Diff line number Diff line change
@@ -1441,8 +1441,9 @@ toolbarpaletteitem:not([place="palette"]) > #stop-reload-button {
transition: opacity 60ms;
}

.previewStack[previewtype="primary"] > .printPreviewBrowser[previewtype="primary"],
.previewStack[previewtype="selection"] > .printPreviewBrowser[previewtype="selection"] {
.previewStack[previewtype="source"] > .printPreviewBrowser[previewtype="source"],
.previewStack[previewtype="selection"] > .printPreviewBrowser[previewtype="selection"],
.previewStack[previewtype="simplified"] > .printPreviewBrowser[previewtype="simplified"] {
display: block;
}

@@ -1461,11 +1462,11 @@ printpreview-pagination {
transition: opacity 100ms 500ms;
}
printpreview-pagination:focus-within,
.previewStack:hover > printpreview-pagination {
.previewStack:hover printpreview-pagination {
opacity: 1;
transition: opacity 100ms;
}
.previewStack[rendering=true] > printpreview-pagination {
.previewStack[rendering=true] printpreview-pagination {
opacity: 0;
}

Original file line number Diff line number Diff line change
@@ -50,9 +50,10 @@ async function testPrintPreview() {
await BrowserTestUtils.waitForCondition(() => !window.gInPrintPreviewMode);
} else {
// Ensure we're showing the preview...
await BrowserTestUtils.waitForCondition(
() => !!document.querySelector(".printPreviewBrowser")
);
await BrowserTestUtils.waitForCondition(() => {
let preview = document.querySelector(".printPreviewBrowser");
return preview && BrowserTestUtils.is_visible(preview);
});

gBrowser.getTabDialogBox(gBrowser.selectedBrowser).abortAllDialogs();
// Wait for the preview to go away
293 changes: 149 additions & 144 deletions toolkit/actors/PrintingChild.jsm
Original file line number Diff line number Diff line change
@@ -191,160 +191,165 @@ class PrintingChild extends JSWindowActorChild {
Cu.reportError(ex);
}

// We make use of a web progress listener in order to know when the content we inject
// into the DOM has finished rendering. If our layout engine is still painting, we
// will wait for MozAfterPaint event to be fired.
let actor = thisWindow.windowGlobalChild.getActor("Printing");
let webProgressListener = {
onStateChange(webProgress, req, flags, status) {
if (flags & Ci.nsIWebProgressListener.STATE_STOP) {
webProgress.removeProgressListener(webProgressListener);
let domUtils = contentWindow.windowUtils;
// Here we tell the parent that we have parsed the document successfully
// using ReaderMode primitives and we are able to enter on preview mode.
if (domUtils.isMozAfterPaintPending) {
let onPaint = function() {
contentWindow.removeEventListener("MozAfterPaint", onPaint);
await new Promise(resolve => {
// We make use of a web progress listener in order to know when the content we inject
// into the DOM has finished rendering. If our layout engine is still painting, we
// will wait for MozAfterPaint event to be fired.
let actor = thisWindow.windowGlobalChild.getActor("Printing");
let webProgressListener = {
onStateChange(webProgress, req, flags, status) {
if (flags & Ci.nsIWebProgressListener.STATE_STOP) {
webProgress.removeProgressListener(webProgressListener);
let domUtils = contentWindow.windowUtils;
// Here we tell the parent that we have parsed the document successfully
// using ReaderMode primitives and we are able to enter on preview mode.
if (domUtils.isMozAfterPaintPending) {
let onPaint = function() {
contentWindow.removeEventListener("MozAfterPaint", onPaint);
actor.sendAsyncMessage("Printing:Preview:ReaderModeReady");
resolve();
};
contentWindow.addEventListener("MozAfterPaint", onPaint);
// This timer is needed for when display list invalidation doesn't invalidate.
setTimeout(() => {
contentWindow.removeEventListener("MozAfterPaint", onPaint);
actor.sendAsyncMessage("Printing:Preview:ReaderModeReady");
resolve();
}, 100);
} else {
actor.sendAsyncMessage("Printing:Preview:ReaderModeReady");
};
contentWindow.addEventListener("MozAfterPaint", onPaint);
// This timer is needed for when display list invalidation doesn't invalidate.
setTimeout(() => {
contentWindow.removeEventListener("MozAfterPaint", onPaint);
actor.sendAsyncMessage("Printing:Preview:ReaderModeReady");
}, 100);
} else {
actor.sendAsyncMessage("Printing:Preview:ReaderModeReady");
resolve();
}
}
}
},

QueryInterface: ChromeUtils.generateQI([
"nsIWebProgressListener",
"nsISupportsWeakReference",
"nsIObserver",
]),
};

// Here we QI the docShell into a nsIWebProgress passing our web progress listener in.
let webProgress = thisWindow.docShell
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebProgress);
webProgress.addProgressListener(
webProgressListener,
Ci.nsIWebProgress.NOTIFY_STATE_REQUEST
);

let document = thisWindow.document;
document.head.innerHTML = "";

// Set base URI of document. Print preview code will read this value to
// populate the URL field in print settings so that it doesn't show
// "about:blank" as its URI.
let headBaseElement = document.createElement("base");
headBaseElement.setAttribute("href", URL);
document.head.appendChild(headBaseElement);

// Create link element referencing aboutReader.css and append it to head
let headStyleElement = document.createElement("link");
headStyleElement.setAttribute("rel", "stylesheet");
headStyleElement.setAttribute(
"href",
"chrome://global/skin/aboutReader.css"
);
headStyleElement.setAttribute("type", "text/css");
document.head.appendChild(headStyleElement);

// Create link element referencing simplifyMode.css and append it to head
headStyleElement = document.createElement("link");
headStyleElement.setAttribute("rel", "stylesheet");
headStyleElement.setAttribute(
"href",
"chrome://global/content/simplifyMode.css"
);
headStyleElement.setAttribute("type", "text/css");
document.head.appendChild(headStyleElement);

document.body.innerHTML = "";

// Create container div (main element) and append it to body
let containerElement = document.createElement("div");
containerElement.setAttribute("id", "container");
document.body.appendChild(containerElement);

// Reader Mode might return null if there's a failure when parsing the document.
// We'll render the error message for the Simplify Page document when that happens.
if (article) {
// Set title of document
document.title = article.title;

// Create header div and append it to container
let headerElement = document.createElement("div");
headerElement.setAttribute("id", "reader-header");
headerElement.setAttribute("class", "header");
containerElement.appendChild(headerElement);

// Jam the article's title and byline into header div
let titleElement = document.createElement("h1");
titleElement.setAttribute("id", "reader-title");
titleElement.textContent = article.title;
headerElement.appendChild(titleElement);

let bylineElement = document.createElement("div");
bylineElement.setAttribute("id", "reader-credits");
bylineElement.setAttribute("class", "credits");
bylineElement.textContent = article.byline;
headerElement.appendChild(bylineElement);

// Display header element
headerElement.style.display = "block";

// Create content div and append it to container
let contentElement = document.createElement("div");
contentElement.setAttribute("class", "content");
containerElement.appendChild(contentElement);

// Jam the article's content into content div
let readerContent = document.createElement("div");
readerContent.setAttribute("id", "moz-reader-content");
contentElement.appendChild(readerContent);

let articleUri = Services.io.newURI(article.url);
let parserUtils = Cc["@mozilla.org/parserutils;1"].getService(
Ci.nsIParserUtils
);
let contentFragment = parserUtils.parseFragment(
article.content,
Ci.nsIParserUtils.SanitizerDropForms |
Ci.nsIParserUtils.SanitizerAllowStyle,
false,
articleUri,
readerContent
},

QueryInterface: ChromeUtils.generateQI([
"nsIWebProgressListener",
"nsISupportsWeakReference",
"nsIObserver",
]),
};

// Here we QI the docShell into a nsIWebProgress passing our web progress listener in.
let webProgress = thisWindow.docShell
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebProgress);
webProgress.addProgressListener(
webProgressListener,
Ci.nsIWebProgress.NOTIFY_STATE_REQUEST
);

readerContent.appendChild(contentFragment);
let document = thisWindow.document;
document.head.innerHTML = "";

// Display reader content element
readerContent.style.display = "block";
} else {
let aboutReaderStrings = Services.strings.createBundle(
"chrome://global/locale/aboutReader.properties"
// Set base URI of document. Print preview code will read this value to
// populate the URL field in print settings so that it doesn't show
// "about:blank" as its URI.
let headBaseElement = document.createElement("base");
headBaseElement.setAttribute("href", URL);
document.head.appendChild(headBaseElement);

// Create link element referencing aboutReader.css and append it to head
let headStyleElement = document.createElement("link");
headStyleElement.setAttribute("rel", "stylesheet");
headStyleElement.setAttribute(
"href",
"chrome://global/skin/aboutReader.css"
);
let errorMessage = aboutReaderStrings.GetStringFromName(
"aboutReader.loadError"
headStyleElement.setAttribute("type", "text/css");
document.head.appendChild(headStyleElement);

// Create link element referencing simplifyMode.css and append it to head
headStyleElement = document.createElement("link");
headStyleElement.setAttribute("rel", "stylesheet");
headStyleElement.setAttribute(
"href",
"chrome://global/content/simplifyMode.css"
);
headStyleElement.setAttribute("type", "text/css");
document.head.appendChild(headStyleElement);

document.body.innerHTML = "";

// Create container div (main element) and append it to body
let containerElement = document.createElement("div");
containerElement.setAttribute("id", "container");
document.body.appendChild(containerElement);

// Reader Mode might return null if there's a failure when parsing the document.
// We'll render the error message for the Simplify Page document when that happens.
if (article) {
// Set title of document
document.title = article.title;

// Create header div and append it to container
let headerElement = document.createElement("div");
headerElement.setAttribute("id", "reader-header");
headerElement.setAttribute("class", "header");
containerElement.appendChild(headerElement);

// Jam the article's title and byline into header div
let titleElement = document.createElement("h1");
titleElement.setAttribute("id", "reader-title");
titleElement.textContent = article.title;
headerElement.appendChild(titleElement);

let bylineElement = document.createElement("div");
bylineElement.setAttribute("id", "reader-credits");
bylineElement.setAttribute("class", "credits");
bylineElement.textContent = article.byline;
headerElement.appendChild(bylineElement);

// Display header element
headerElement.style.display = "block";

// Create content div and append it to container
let contentElement = document.createElement("div");
contentElement.setAttribute("class", "content");
containerElement.appendChild(contentElement);

// Jam the article's content into content div
let readerContent = document.createElement("div");
readerContent.setAttribute("id", "moz-reader-content");
contentElement.appendChild(readerContent);

let articleUri = Services.io.newURI(article.url);
let parserUtils = Cc["@mozilla.org/parserutils;1"].getService(
Ci.nsIParserUtils
);
let contentFragment = parserUtils.parseFragment(
article.content,
Ci.nsIParserUtils.SanitizerDropForms |
Ci.nsIParserUtils.SanitizerAllowStyle,
false,
articleUri,
readerContent
);

document.title = errorMessage;
readerContent.appendChild(contentFragment);

// Create reader message div and append it to body
let readerMessageElement = document.createElement("div");
readerMessageElement.setAttribute("class", "reader-message");
readerMessageElement.textContent = errorMessage;
containerElement.appendChild(readerMessageElement);
// Display reader content element
readerContent.style.display = "block";
} else {
let aboutReaderStrings = Services.strings.createBundle(
"chrome://global/locale/aboutReader.properties"
);
let errorMessage = aboutReaderStrings.GetStringFromName(
"aboutReader.loadError"
);

// Display reader message element
readerMessageElement.style.display = "block";
}
document.title = errorMessage;

// Create reader message div and append it to body
let readerMessageElement = document.createElement("div");
readerMessageElement.setAttribute("class", "reader-message");
readerMessageElement.textContent = errorMessage;
containerElement.appendChild(readerMessageElement);

// Display reader message element
readerMessageElement.style.display = "block";
}
});
}

enterPrintPreview(
6 changes: 6 additions & 0 deletions toolkit/components/printing/content/print.css
Original file line number Diff line number Diff line change
@@ -296,3 +296,9 @@ input[type="number"].photon-number::-moz-number-spin-down:hover {
background-color: var(--in-content-button-background-hover);
color: var(--in-content-button-text-color-hover);
}

input[type="checkbox"]:disabled + label,
input[type="radio"]:disabled + label,
input[type="radio"]:disabled + span > label {
opacity: 0.5;
}
24 changes: 19 additions & 5 deletions toolkit/components/printing/content/print.html
Original file line number Diff line number Diff line change
@@ -202,20 +202,34 @@ <h2 data-l10n-id="printui-title"></h2>
</select>
</section>

<section id="source-version-section" class="section-block">
<label id="source-version-label" data-l10n-id="printui-source-label"></label>
<div role="radiogroup" aria-labelledby="source-version-label">
<label id="source-version-source" class="row cols-2">
<input is="setting-radio" name="source-version" value="source" id="source-version-source-radio" data-setting-name="sourceVersion" checked>
<span data-l10n-id="printui-source-radio"></span>
</label>
<label id="source-version-selection" class="row cols-2">
<input is="setting-radio" name="source-version" value="selection" id="source-version-selection-radio" data-setting-name="sourceVersion">
<span data-l10n-id="printui-selection-radio"></span>
</label>
<label id="source-version-simplified" class="row cols-2">
<input is="setting-radio" name="source-version" value="simplified" id="source-version-simplified-radio" data-setting-name="sourceVersion">
<span data-l10n-id="printui-simplify-page-radio"></span>
</label>
</div>
</section>

<section id="more-settings-options" class="section-block">
<label class="block-label" data-l10n-id="printui-options"></label>
<label id="headers-footers" class="row cols-2">
<input is="setting-checkbox" id="headers-footers-enabled" data-setting-name="printFootersHeaders">
<span data-l10n-id="printui-headers-footers-checkbox"></span>
</label>
<label id="backgrounds" class="row cols-2">
<input is="setting-checkbox" id="backgrounds-enabled" data-setting-name="printBackgrounds">
<input is="print-backgrounds" id="backgrounds-enabled" data-setting-name="printBackgrounds">
<span data-l10n-id="printui-backgrounds-checkbox"></span>
</label>
<label id="print-selection-container" class="row cols-2" hidden>
<input is="setting-checkbox" id="print-selection-enabled" data-setting-name="printSelectionOnly">
<span data-l10n-id="printui-selection-checkbox"></span>
</label>
</section>

</details>
243 changes: 130 additions & 113 deletions toolkit/components/printing/content/print.js

Large diffs are not rendered by default.

77 changes: 27 additions & 50 deletions toolkit/components/printing/content/printPreviewPagination.js
Original file line number Diff line number Diff line change
@@ -31,19 +31,25 @@ customElements.define(
}

get previewBrowser() {
if (!this._previewBrowser) {
// Assuming we're a sibling of our preview browser.
this._previewBrowser = this.parentNode.querySelector(
".printPreviewBrowser"
);
}
return this._previewBrowser;
}

set previewBrowser(aBrowser) {
this._previewBrowser = aBrowser;
}

observePreviewBrowser(browser) {
if (browser == this.previewBrowser || !this.isConnected) {
return;
}
this.previewBrowser = browser;
this.mutationObserver.disconnect();
this.mutationObserver.observe(browser, {
attributes: ["current-page", "sheet-count"],
});
this.updateFromBrowser();
}

connectedCallback() {
MozXULElement.insertFTLIfNeeded("toolkit/printing/printPreview.ftl");

@@ -63,46 +69,9 @@ customElements.define(

this.shadowRoot.addEventListener("click", this);

let knownAttrs = {
"sheet-count": "sheetCount",
"current-page": "currentPage",
};
this.mutationObserver = new MutationObserver(changes => {
let opts = {};
for (let change of changes) {
let { attributeName, target, type } = change;
if (type == "attributes" && attributeName in knownAttrs) {
opts[knownAttrs[attributeName]] = parseInt(
target.getAttribute(attributeName),
10
);
}
}
if (opts.sheetCount || opts.currentPage) {
this.update(opts);
}
});
this.mutationObserver.observe(this.previewBrowser, {
attributes: ["current-page", "sheet-count"],
});

this.currentPreviewBrowserObserver = new MutationObserver(changes => {
for (let change of changes) {
if (change.attributeName == "previewtype") {
let previewType = change.target.getAttribute("previewtype");
this.previewBrowser = change.target.querySelector(
`browser[previewtype="${previewType}"]`
);
this.mutationObserver.disconnect();
this.mutationObserver.observe(this.previewBrowser, {
attributes: ["current-page", "sheet-count"],
});
}
}
});
this.currentPreviewBrowserObserver.observe(this.parentNode, {
attributes: ["previewtype"],
});
this.mutationObserver = new MutationObserver(() =>
this.updateFromBrowser()
);

// Initial render with some default values
// We'll be updated with real values when available
@@ -186,10 +155,6 @@ customElements.define(

update(data = {}) {
if (data.sheetCount) {
if (this.sheetCount !== data.sheetCount || this.currentSheet !== 1) {
// when sheet count changes, scroll position will get reset
this.currentSheet = 1;
}
this.sheetCount = data.sheetCount;
}
if (data.currentPage) {
@@ -204,5 +169,17 @@ customElements.define(
}
);
}

updateFromBrowser() {
let sheetCount = parseInt(
this.previewBrowser.getAttribute("sheet-count"),
10
);
let currentPage = parseInt(
this.previewBrowser.getAttribute("current-page"),
10
);
this.update({ sheetCount, currentPage });
}
}
);
392 changes: 275 additions & 117 deletions toolkit/components/printing/content/printUtils.js

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions toolkit/components/printing/tests/browser.ini
Original file line number Diff line number Diff line change
@@ -36,12 +36,14 @@ support-files =
file_print_pdf_on_frame_load.html
file_multi_page_pdf.pdf
[browser_print_scaling.js]
[browser_print_simplified_mode.js]
[browser_sheet_count.js]
[browser_ui_labels.js]
[browser_window_print.js]
support-files =
file_window_print.html
file_window_print_delayed_during_load.html
file_window_print_oop_iframe.html
file_window_print_sandboxed_iframe.html
file_window_print_another_iframe_and_remove.html
file_window_print_iframe_remove_on_afterprint.html
20 changes: 13 additions & 7 deletions toolkit/components/printing/tests/browser_preview_in_container.js
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ const TEST_PATH = getRootDirectory(gTestPath).replace(

async function runTest() {
is(
document.querySelector(".printPreviewBrowser"),
document.querySelector("print-preview"),
null,
"There shouldn't be any print preview browser"
);
@@ -22,14 +22,20 @@ async function runTest() {
);

// Wait for window.print() to run and ensure we're showing the preview...
await waitForPreviewVisible();

let printPreviewEl = document.querySelector("print-preview");
await BrowserTestUtils.waitForCondition(
() => !!document.querySelector(".printPreviewBrowser")
() => !!printPreviewEl.settingsBrowser.contentWindow._initialized
);
await printPreviewEl.settingsBrowser.contentWindow._initialized;
let contentFound = await SpecialPowers.spawn(
printPreviewEl.sourceBrowser,
[],
() => {
return !!content.document.getElementById("printed");
}
);

let previewBrowser = document.querySelector(".printPreviewBrowser");
let contentFound = await SpecialPowers.spawn(previewBrowser, [], () => {
return !!content.document.getElementById("printed");
});
ok(contentFound, "We should find the preview content.");
BrowserTestUtils.removeTab(gBrowser.selectedTab);
}
147 changes: 68 additions & 79 deletions toolkit/components/printing/tests/browser_preview_navigation.js
Original file line number Diff line number Diff line change
@@ -54,30 +54,37 @@ add_task(async function testToolbarVisibility() {
await PrintHelper.withTestPage(async helper => {
await helper.startPrint();

let paginationElem = document.querySelector(".printPreviewNavigation");
let previewStack = document.querySelector(".previewStack");

// The toolbar has 0 opacity until we hover or focus it
is(getComputedStyle(paginationElem).opacity, "0", "Initially transparent");
is(
getComputedStyle(helper.paginationElem).opacity,
"0",
"Initially transparent"
);

let visiblePromise = waitUntilVisible(paginationElem);
paginationElem.shadowRoot.querySelector("#navigateEnd").focus();
let visiblePromise = waitUntilVisible(helper.paginationElem);
helper.paginationElem.shadowRoot.querySelector("#navigateEnd").focus();
await visiblePromise;
is(
getComputedStyle(paginationElem).opacity,
getComputedStyle(helper.paginationElem).opacity,
"1",
"Opaque with button focused"
);

await EventUtils.synthesizeKey("KEY_Tab", {});
await waitUntilTransparent(paginationElem);
is(getComputedStyle(paginationElem).opacity, "0", "Returns to transparent");
await waitUntilTransparent(helper.paginationElem);
is(
getComputedStyle(helper.paginationElem).opacity,
"0",
"Returns to transparent"
);

visiblePromise = waitUntilVisible(paginationElem);
visiblePromise = waitUntilVisible(helper.paginationElem);
info("Waiting for mousemove event, and for the toolbar to become opaque");
await mouseMoveAndWait(previewStack);
await visiblePromise;
is(getComputedStyle(paginationElem).opacity, "1", "Opaque toolbar");
is(getComputedStyle(helper.paginationElem).opacity, "1", "Opaque toolbar");

// put the mouse back where it won't interfere with later tests
await mouseMoveAndWait(gURLBar.textbox);
@@ -89,14 +96,9 @@ add_task(async function testPreviewSheetCount() {
await PrintHelper.withTestPage(async helper => {
await helper.startPrint();

let paginationElem = document.querySelector(".printPreviewNavigation");
let paginationSheetIndicator = paginationElem.shadowRoot.querySelector(
"#sheetIndicator"
);

// We have to wait for the first _updatePrintPreview to get the sheet count
await waitForPageStatusUpdate(
paginationSheetIndicator,
helper.paginationSheetIndicator,
{ sheetNum: 1, sheetCount: 3 },
"Paginator indicates the correct number of sheets"
);
@@ -106,7 +108,7 @@ add_task(async function testPreviewSheetCount() {
pageRanges: ["1", "1"],
});
await waitForPageStatusUpdate(
paginationSheetIndicator,
helper.paginationSheetIndicator,
{ sheetNum: 1, sheetCount: 1 },
"Indicates the updated number of sheets"
);
@@ -119,17 +121,13 @@ add_task(async function testPreviewScroll() {
await PrintHelper.withTestPage(async helper => {
await helper.startPrint();

let paginationElem = document.querySelector(".printPreviewNavigation");
let paginationSheetIndicator = paginationElem.shadowRoot.querySelector(
"#sheetIndicator"
);
// Wait for the first _updatePrintPreview before interacting with the preview
await waitForPageStatusUpdate(
paginationSheetIndicator,
helper.paginationSheetIndicator,
{ sheetNum: 1, sheetCount: 3 },
"Paginator indicates the correct number of sheets"
);
let previewBrowser = PrintUtils.getPreviewBrowser();
let previewBrowser = helper.currentPrintPreviewBrowser;

// scroll down the document
// and verify the indicator is updated correctly
@@ -142,7 +140,7 @@ add_task(async function testPreviewScroll() {
EventUtils.synthesizeKey("VK_PAGE_DOWN", {}, content);
});
await waitForPageStatusUpdate(
paginationSheetIndicator,
helper.paginationSheetIndicator,
{ sheetNum: 2, sheetCount: 3 },
"Indicator updates on scroll"
);
@@ -157,84 +155,80 @@ add_task(async function testPreviewNavigationCommands() {
await PrintHelper.withTestPage(async helper => {
await helper.startPrint();

let paginationElem = document.querySelector(".printPreviewNavigation");
let paginationSheetIndicator = paginationElem.shadowRoot.querySelector(
"#sheetIndicator"
);
// Wait for the first _updatePrintPreview before interacting with the preview
await waitForPageStatusUpdate(
paginationSheetIndicator,
helper.paginationSheetIndicator,
{ sheetNum: 1, sheetCount: 3 },
"Paginator indicates the correct number of sheets"
);

// click the navigation buttons
// and verify the indicator is updated correctly
EventUtils.synthesizeMouseAtCenter(
paginationElem.shadowRoot.querySelector("#navigateNext"),
helper.paginationElem.shadowRoot.querySelector("#navigateNext"),
{}
);
await waitForPageStatusUpdate(
paginationSheetIndicator,
helper.paginationSheetIndicator,
{ sheetNum: 2, sheetCount: 3 },
"Indicator updates on navigation"
"Indicator updates on navigation to next"
);

EventUtils.synthesizeMouseAtCenter(
paginationElem.shadowRoot.querySelector("#navigatePrevious"),
helper.paginationElem.shadowRoot.querySelector("#navigatePrevious"),
{}
);
await waitForPageStatusUpdate(
paginationSheetIndicator,
helper.paginationSheetIndicator,
{ sheetNum: 1, sheetCount: 3 },
"Indicator updates on navigation to previous"
);

EventUtils.synthesizeMouseAtCenter(
paginationElem.shadowRoot.querySelector("#navigateEnd"),
helper.paginationElem.shadowRoot.querySelector("#navigateEnd"),
{}
);
await waitForPageStatusUpdate(
paginationSheetIndicator,
helper.paginationSheetIndicator,
{ sheetNum: 3, sheetCount: 3 },
"Indicator updates on navigation to end"
);

EventUtils.synthesizeMouseAtCenter(
paginationElem.shadowRoot.querySelector("#navigateHome"),
helper.paginationElem.shadowRoot.querySelector("#navigateHome"),
{}
);
await waitForPageStatusUpdate(
paginationSheetIndicator,
helper.paginationSheetIndicator,
{ sheetNum: 1, sheetCount: 3 },
"Indicator updates on navigation to start"
);

// Test rapid clicks on the navigation buttons
EventUtils.synthesizeMouseAtCenter(
paginationElem.shadowRoot.querySelector("#navigateNext"),
helper.paginationElem.shadowRoot.querySelector("#navigateNext"),
{}
);
EventUtils.synthesizeMouseAtCenter(
paginationElem.shadowRoot.querySelector("#navigateNext"),
helper.paginationElem.shadowRoot.querySelector("#navigateNext"),
{}
);
await waitForPageStatusUpdate(
paginationSheetIndicator,
helper.paginationSheetIndicator,
{ sheetNum: 3, sheetCount: 3 },
"2 successive 'next' clicks correctly update the sheet indicator"
);

EventUtils.synthesizeMouseAtCenter(
paginationElem.shadowRoot.querySelector("#navigatePrevious"),
helper.paginationElem.shadowRoot.querySelector("#navigatePrevious"),
{}
);
EventUtils.synthesizeMouseAtCenter(
paginationElem.shadowRoot.querySelector("#navigatePrevious"),
helper.paginationElem.shadowRoot.querySelector("#navigatePrevious"),
{}
);
await waitForPageStatusUpdate(
paginationSheetIndicator,
helper.paginationSheetIndicator,
{ sheetNum: 1, sheetCount: 3 },
"2 successive 'previous' clicks correctly update the sheet indicator"
);
@@ -249,12 +243,9 @@ add_task(async function testMultiplePreviewNavigation() {
await PrintHelper.withTestPage(async helper => {
await helper.startPrint();
const tab1 = gBrowser.selectedTab;
let sheetIndicator = document
.querySelector(".printPreviewNavigation")
.shadowRoot.querySelector("#sheetIndicator");

await waitForPageStatusUpdate(
sheetIndicator,
helper.paginationSheetIndicator,
{ sheetNum: 1, sheetCount: 3 },
"Indicator has the correct initial sheetCount"
);
@@ -267,7 +258,7 @@ add_task(async function testMultiplePreviewNavigation() {
await helper2.startPrint();

let [previewBrowser1, previewBrowser2] = document.querySelectorAll(
".printPreviewBrowser[previewtype='primary']"
".printPreviewBrowser[previewtype='source']"
);
ok(previewBrowser1 && previewBrowser2, "There are 2 preview browsers");

@@ -280,9 +271,11 @@ add_task(async function testMultiplePreviewNavigation() {
previewBrowser1,
"toolbar1 has the correct previewBrowser"
);
sheetIndicator = toolbar1.shadowRoot.querySelector("#sheetIndicator");
ok(
compare10nArgs(sheetIndicator, { sheetNum: 1, sheetCount: 3 }),
compare10nArgs(helper.paginationSheetIndicator, {
sheetNum: 1,
sheetCount: 3,
}),
"First toolbar has the correct content"
);

@@ -291,24 +284,25 @@ add_task(async function testMultiplePreviewNavigation() {
previewBrowser2,
"toolbar2 has the correct previewBrowser"
);
sheetIndicator = toolbar2.shadowRoot.querySelector("#sheetIndicator");
ok(
compare10nArgs(sheetIndicator, { sheetNum: 1, sheetCount: 1 }),
compare10nArgs(helper2.paginationSheetIndicator, {
sheetNum: 1,
sheetCount: 1,
}),
"2nd toolbar has the correct content"
);

// Switch back to the first tab and ensure the correct preview navigation is updated when clicked
await BrowserTestUtils.switchTab(gBrowser, tab1);
sheetIndicator = toolbar1.shadowRoot.querySelector("#sheetIndicator");

EventUtils.synthesizeMouseAtCenter(
toolbar1.shadowRoot.querySelector("#navigateNext"),
{}
);
await waitForPageStatusUpdate(
sheetIndicator,
helper.paginationSheetIndicator,
{ sheetNum: 2, sheetCount: 3 },
"Indicator updates on navigation"
"Indicator updates on navigation multiple"
);

gBrowser.removeTab(tab2);
@@ -324,50 +318,46 @@ add_task(async function testPreviewNavigationSelection() {

await helper.startPrint();

let paginationElem = document.querySelector(".printPreviewNavigation");
let paginationSheetIndicator = paginationElem.shadowRoot.querySelector(
"#sheetIndicator"
);
// Wait for the first _updatePrintPreview before interacting with the preview
await waitForPageStatusUpdate(
paginationSheetIndicator,
helper.paginationSheetIndicator,
{ sheetNum: 1, sheetCount: 3 },
"Paginator indicates the correct number of sheets"
);

// click a navigation button
// and verify the indicator is updated correctly
EventUtils.synthesizeMouseAtCenter(
paginationElem.shadowRoot.querySelector("#navigateNext"),
helper.paginationElem.shadowRoot.querySelector("#navigateNext"),
{}
);
await waitForPageStatusUpdate(
paginationSheetIndicator,
helper.paginationSheetIndicator,
{ sheetNum: 2, sheetCount: 3 },
"Indicator updates on navigation"
"Indicator updates on navigation next selection"
);

await helper.openMoreSettings();
let printSelect = helper.get("print-selection-container");
let printSelect = helper.get("source-version-selection-radio");
await helper.waitForPreview(() => helper.click(printSelect));

// Wait for the first _updatePrintPreview before interacting with the preview
await waitForPageStatusUpdate(
paginationSheetIndicator,
helper.paginationSheetIndicator,
{ sheetNum: 1, sheetCount: 2 },
"Paginator indicates the correct number of sheets"
);

// click a navigation button
// and verify the indicator is updated correctly
EventUtils.synthesizeMouseAtCenter(
paginationElem.shadowRoot.querySelector("#navigateNext"),
helper.paginationElem.shadowRoot.querySelector("#navigateNext"),
{}
);
await waitForPageStatusUpdate(
paginationSheetIndicator,
helper.paginationSheetIndicator,
{ sheetNum: 2, sheetCount: 2 },
"Indicator updates on navigation"
"Indicator updates on navigation next selection 2"
);

// move focus before closing the dialog
@@ -382,38 +372,37 @@ add_task(async function testPaginatorAfterSettingsUpdate() {
helper.addMockPrinter(mockPrinterName);
await helper.startPrint();

let paginationElem = document.querySelector(".printPreviewNavigation");
let paginationSheetIndicator = paginationElem.shadowRoot.querySelector(
"#sheetIndicator"
);
// Wait for the first _updatePrintPreview before interacting with the preview
await waitForPageStatusUpdate(
paginationSheetIndicator,
helper.paginationSheetIndicator,
{ sheetNum: 1, sheetCount: 3 },
"Paginator indicates the correct number of sheets"
);

// click the navigation buttons
// and verify the indicator is updated correctly
EventUtils.synthesizeMouseAtCenter(
paginationElem.shadowRoot.querySelector("#navigateNext"),
helper.paginationElem.shadowRoot.querySelector("#navigateNext"),
{}
);
await waitForPageStatusUpdate(
paginationSheetIndicator,
helper.paginationSheetIndicator,
{ sheetNum: 2, sheetCount: 3 },
"Indicator updates on navigation"
"Indicator updates on navigation next after update"
);

// Select a new printer
await helper.dispatchSettingsChange({ printerName: mockPrinterName });
await waitForPageStatusUpdate(
paginationSheetIndicator,
helper.paginationSheetIndicator,
{ sheetNum: 1, sheetCount: 3 },
"Indicator updates on navigation"
"Indicator updates on navigation next after printer change"
);
ok(
compare10nArgs(paginationSheetIndicator, { sheetNum: 1, sheetCount: 3 }),
compare10nArgs(helper.paginationSheetIndicator, {
sheetNum: 1,
sheetCount: 3,
}),
"Sheet indicator has correct value"
);

Original file line number Diff line number Diff line change
@@ -38,3 +38,11 @@ add_task(async function test() {

BrowserTestUtils.removeTab(tab);
});

add_task(async function testTabModal() {
await PrintHelper.withTestPage(async helper => {
await helper.startPrint();
ok(true, "We did not crash.");
await helper.closeDialog();
}, "file_coop_header.html");
});
22 changes: 12 additions & 10 deletions toolkit/components/printing/tests/browser_print_context_menu.js
Original file line number Diff line number Diff line change
@@ -43,19 +43,21 @@ add_task(async function testPrintFrame() {
frameContextMenu.activateItem(item);
await popupHiddenPromise;

await BrowserTestUtils.waitForCondition(
() => !!document.querySelector(".printPreviewBrowser")
);
let helper = new PrintHelper(browser);

await helper.waitForDialog();

let previewBrowser = document.querySelector(
".printPreviewBrowser[previewtype='primary']"
let previewBrowser = helper.currentPrintPreviewBrowser;
is(
previewBrowser.getAttribute("previewtype"),
"source",
"Source preview was rendered"
);
let helper = new PrintHelper(browser);

let textContent = await TestUtils.waitForCondition(() =>
SpecialPowers.spawn(previewBrowser, [], function() {
return content.document.body.textContent;
})
let textContent = await SpecialPowers.spawn(
previewBrowser,
[],
() => content.document.body.textContent
);

is(textContent, "Inner frame", "Correct content loaded");
11 changes: 6 additions & 5 deletions toolkit/components/printing/tests/browser_print_frame.js
Original file line number Diff line number Diff line change
@@ -41,12 +41,13 @@ add_task(async function print_frame() {
printFrameOnly: true,
});

await helper.waitForDialog({ waitFor: "loadComplete" });
// Wait for the dialog to be fully ready. The initial preview will be
// done at this point.
await helper.waitForDialog();

let previewBrowser = document.querySelector(".printPreviewBrowser");
let previewText = () => getPreviewText(previewBrowser);
// The preview process is async, wait for it to not be empty.
let textContent = await TestUtils.waitForCondition(previewText);
let textContent = await getPreviewText(
helper.currentPrintPreviewBrowser
);
is(textContent, "some text", "Correct content loaded");

let file = helper.mockFilePicker(`browser_print_frame-${i++}.pdf`);
Original file line number Diff line number Diff line change
@@ -29,9 +29,7 @@ add_task(async function test_print_pdf_on_frame_load() {
);

let helper = new PrintHelper(browser);
await TestUtils.waitForCondition(
() => !!document.querySelector(".printPreviewBrowser")
);
await waitForPreviewVisible();

info("Preview shown, waiting for it to be updated...");

56 changes: 23 additions & 33 deletions toolkit/components/printing/tests/browser_print_selection.js
Original file line number Diff line number Diff line change
@@ -48,9 +48,7 @@ add_task(async function print_selection() {
printSelectionOnly: true,
});

await BrowserTestUtils.waitForCondition(
() => !!document.querySelector(".printPreviewBrowser")
);
await waitForPreviewVisible();

let previewBrowser = document.querySelector(
".printPreviewBrowser[previewtype='selection']"
@@ -62,8 +60,11 @@ add_task(async function print_selection() {

let printSelect = document
.querySelector(".printSettingsBrowser")
.contentDocument.querySelector("#print-selection-enabled");
ok(!printSelect.hidden, "Print selection checkbox is shown");
.contentDocument.querySelector("#source-version-selection-radio");
ok(
BrowserTestUtils.is_visible(printSelect),
"Print selection checkbox is shown"
);
ok(printSelect.checked, "Print selection checkbox is checked");

let file = helper.mockFilePicker(`browser_print_selection-${i++}.pdf`);
@@ -82,8 +83,11 @@ add_task(async function no_print_selection() {
await helper.startPrint();
await helper.openMoreSettings();

let printSelect = helper.get("print-selection-container");
ok(printSelect.hidden, "Print selection checkbox is hidden");
let printSelect = helper.get("source-version-selection");
ok(
BrowserTestUtils.is_hidden(printSelect),
"Print selection checkbox is hidden"
);
await helper.closeDialog();
});
});
@@ -97,22 +101,15 @@ add_task(async function print_selection_switch() {

await helper.startPrint();
await helper.openMoreSettings();
let printSelect = helper.get("print-selection-container");
ok(!printSelect.checked, "Print selection checkbox is not checked");

let selectionBrowser = document.querySelector(
".printPreviewBrowser[previewtype='selection']"
);
let primaryBrowser = document.querySelector(
".printPreviewBrowser[previewtype='primary']"
);

let selectedText = "Article title";
let fullText = await getPreviewText(primaryBrowser);
let printSource = helper.get("source-version-source-radio");
ok(printSource.checked, "Print source radio is checked");
let printSelect = helper.get("source-version-selection-radio");
ok(!printSelect.checked, "Print selection radio is not checked");

function getCurrentBrowser(previewType) {
let browser =
previewType == "selection" ? selectionBrowser : primaryBrowser;
let browser = document.querySelector(
`.printPreviewBrowser[previewtype="${previewType}"]`
);
is(
browser.parentElement.getAttribute("previewtype"),
previewType,
@@ -121,16 +118,13 @@ add_task(async function print_selection_switch() {
return browser;
}

let selectedText = "Article title";
let fullText = await getPreviewText(getCurrentBrowser("source"));

helper.assertSettingsMatch({
printSelectionOnly: false,
});

is(
selectionBrowser.parentElement.getAttribute("previewtype"),
"primary",
"Print selection browser is not shown"
);

await helper.assertSettingsChanged(
{ printSelectionOnly: false },
{ printSelectionOnly: true },
@@ -145,12 +139,8 @@ add_task(async function print_selection_switch() {
{ printSelectionOnly: true },
{ printSelectionOnly: false },
async () => {
await helper.waitForPreview(() => helper.click(printSelect));
let previewType = selectionBrowser.parentElement.getAttribute(
"previewtype"
);
is(previewType, "primary", "Print selection browser is not shown");
let text = await getPreviewText(getCurrentBrowser(previewType));
await helper.waitForPreview(() => helper.click(printSource));
let text = await getPreviewText(getCurrentBrowser("source"));
is(text, fullText, "Correct content loaded");
}
);
240 changes: 240 additions & 0 deletions toolkit/components/printing/tests/browser_print_simplified_mode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */

"use strict";

add_task(async function switch_print_preview_browsers() {
await PrintHelper.withTestPage(async helper => {
// Wait for the article state to be determined.
await helper.waitForReaderModeReady();

// Start print preview.
await helper.startPrint();
let sourcePreviewBrowser = helper.currentPrintPreviewBrowser;

{
// Assert that we are showing the initial content on default print preview browser
let [headerText, headingText] = await SpecialPowers.spawn(
sourcePreviewBrowser,
[],
async function() {
return [
content.document.querySelector("header").textContent,
content.document.querySelector("h1").textContent,
];
}
);
is(headerText, "Site header", "Should have initial content.");
is(headingText, "Article title", "Should have initial title.");
}

// Here we call simplified mode
await helper.openMoreSettings();
let simplifyRadio = helper.get("source-version-simplified-radio");
ok(!simplifyRadio.checked, "Simplify page is not checked");
ok(BrowserTestUtils.is_visible(simplifyRadio), "Simplify is shown");

await helper.waitForPreview(() => helper.click(simplifyRadio));
let simplifiedPreviewBrowser = helper.currentPrintPreviewBrowser;
is(
simplifiedPreviewBrowser.getAttribute("previewtype"),
"simplified",
"Simplified browser was rendered"
);
is(
simplifiedPreviewBrowser.closest("stack").getAttribute("previewtype"),
"simplified",
"Simplified browser is selected"
);
ok(
BrowserTestUtils.is_visible(simplifiedPreviewBrowser),
"Simplified browser is visible"
);
ok(simplifyRadio.checked, "Simplify page is checked");

{
// Assert that we are showing custom content on simplified print preview browser
let [hasHeader, headingText] = await SpecialPowers.spawn(
simplifiedPreviewBrowser,
[],
async function() {
return [
!!content.document.querySelector("header"),
content.document.querySelector("h1").textContent,
];
}
);
ok(!hasHeader, "The header was simplified out");
is(headingText, "Article title", "The heading is still there");
}

// Switch back to default print preview content
let sourceRadio = helper.get("source-version-source-radio");
ok(!sourceRadio.checked, "Source is not checked");
await helper.waitForPreview(() => helper.click(sourceRadio));
is(
helper.currentPrintPreviewBrowser,
sourcePreviewBrowser,
"Source browser was rendered"
);
is(
sourcePreviewBrowser.getAttribute("previewtype"),
"source",
"Source browser was rendered"
);
is(
sourcePreviewBrowser.closest("stack").getAttribute("previewtype"),
"source",
"Source browser is selected"
);
ok(
BrowserTestUtils.is_visible(sourcePreviewBrowser),
"Source browser is visible"
);
ok(sourceRadio.checked, "Source version is checked");

{
// Assert that we are showing the initial content on default print preview browser
let headerText = await SpecialPowers.spawn(
sourcePreviewBrowser,
[],
async function() {
return content.document.querySelector("header").textContent;
}
);
is(headerText, "Site header", "Should have initial content.");
}

await helper.closeDialog();
}, "simplifyArticleSample.html");
});

add_task(async function testPrintBackgroundsDisabledSimplified() {
await PrintHelper.withTestPage(async helper => {
// Wait for the article state to be determined.
await helper.waitForReaderModeReady();
await helper.startPrint();

helper.assertPreviewedWithSettings({
printBGImages: false,
printBGColors: false,
});

await helper.openMoreSettings();

let printBackgrounds = helper.get("backgrounds-enabled");
ok(!printBackgrounds.checked, "Print backgrounds is not checked");
ok(!printBackgrounds.disabled, "Print backgrounds in not disabled");

await helper.assertSettingsChanged(
{ printBGImages: false, printBGColors: false },
{ printBGImages: true, printBGColors: true },
async () => {
await helper.waitForPreview(() => helper.click(printBackgrounds));
}
);

// Print backgrounds was enabled for preview.
ok(printBackgrounds.checked, "Print backgrounds is checked");
ok(!printBackgrounds.disabled, "Print backgrounds is not disabled");
helper.assertPreviewedWithSettings({
printBGImages: true,
printBGColors: true,
});

let simplifyRadio = helper.get("source-version-simplified-radio");
ok(!simplifyRadio.checked, "Simplify page is not checked");
ok(BrowserTestUtils.is_visible(simplifyRadio), "Simplify is shown");

// Switch to simplified mode.
await helper.waitForPreview(() => helper.click(simplifyRadio));

// Print backgrounds should be disabled, it's incompatible with simplified.
ok(!printBackgrounds.checked, "Print backgrounds is now unchecked");
ok(printBackgrounds.disabled, "Print backgrounds has been disabled");
helper.assertPreviewedWithSettings({
printBGImages: false,
printBGColors: false,
});

// Switch back to source, printBackgrounds is remembered.
let sourceRadio = helper.get("source-version-source-radio");
ok(!sourceRadio.checked, "Source is not checked");
ok(BrowserTestUtils.is_visible(sourceRadio), "Source is shown");

await helper.waitForPreview(() => helper.click(sourceRadio));

ok(printBackgrounds.checked, "Print backgrounds setting was remembered");
ok(!printBackgrounds.disabled, "Print backgrounds can be changed again");
helper.assertPreviewedWithSettings({
printBGImages: true,
printBGColors: true,
});

await helper.closeDialog();
}, "simplifyArticleSample.html");
});

add_task(async function testSimplifyHiddenNonArticle() {
await PrintHelper.withTestPage(async helper => {
await helper.startPrint();
await helper.openMoreSettings();
let sourceVersionSection = helper.get("source-version-section");
ok(
BrowserTestUtils.is_hidden(sourceVersionSection),
"Source version is hidden"
);
await helper.closeDialog();
}, "simplifyNonArticleSample.html");
});

add_task(async function testSimplifyNonArticleTabModal() {
await PrintHelper.withTestPage(async helper => {
let tab = gBrowser.selectedTab;

// Trick browser to think loaded tab has isArticle property set as true
tab.linkedBrowser.isArticle = true;

// Enter print preview
await helper.startPrint();

// Assert that we are showing the initial content on default print preview browser
await SpecialPowers.spawn(
helper.currentPrintPreviewBrowser,
[],
async () => {
is(
content.document.title,
"Non article title",
"Should have initial content."
);
}
);

await helper.openMoreSettings();

// Simplify the page.
let simplifyRadio = helper.get("source-version-simplified-radio");
ok(!simplifyRadio.checked, "Simplify is off");
await helper.waitForPreview(() => helper.click(simplifyRadio));
let simplifiedPreviewBrowser = helper.currentPrintPreviewBrowser;
is(
simplifiedPreviewBrowser.getAttribute("previewtype"),
"simplified",
"The simplified browser is shown"
);

// Assert that simplify page option is checked
ok(simplifyRadio.checked, "Should have simplify page option checked");

// Assert that we are showing recovery content on simplified print preview browser
await SpecialPowers.spawn(simplifiedPreviewBrowser, [], async () => {
await ContentTaskUtils.waitForCondition(
() => content.document.title === "Failed to load article from page",
"Simplified document title should be updated with recovery title."
);
});

await helper.closeDialog();
}, "simplifyNonArticleSample.html");
});
68 changes: 43 additions & 25 deletions toolkit/components/printing/tests/browser_window_print.js
Original file line number Diff line number Diff line change
@@ -33,9 +33,8 @@ add_task(async function test_print_blocks() {
"Waiting for the first window.print() to run and ensure we're showing the preview..."
);

await BrowserTestUtils.waitForCondition(
() => !!document.querySelector(".printPreviewBrowser")
);
let helper = new PrintHelper(browser);
await helper.waitForDialog();

{
let [before, afterFirst] = await SpecialPowers.spawn(
@@ -55,9 +54,7 @@ add_task(async function test_print_blocks() {

gBrowser.getTabDialogBox(browser).abortAllDialogs();

await BrowserTestUtils.waitForCondition(
() => !!document.querySelector(".printPreviewBrowser")
);
await helper.waitForDialog();

{
let [before, afterFirst, afterSecond] = await SpecialPowers.spawn(
@@ -100,9 +97,8 @@ add_task(async function test_print_delayed_during_load() {
"Waiting for the first window.print() to run and ensure we're showing the preview..."
);

await BrowserTestUtils.waitForCondition(
() => !!document.querySelector(".printPreviewBrowser")
);
let helper = new PrintHelper(browser);
await helper.waitForDialog();

// The print dialog is open, should be open after onload.
{
@@ -141,9 +137,8 @@ add_task(async function test_print_on_sandboxed_frame() {
"Waiting for the first window.print() to run and ensure we're showing the preview..."
);

await BrowserTestUtils.waitForCondition(
() => !!document.querySelector(".printPreviewBrowser")
);
let helper = new PrintHelper(browser);
await helper.waitForDialog();

isnot(
document.querySelector(".printPreviewBrowser"),
@@ -173,10 +168,7 @@ add_task(async function test_print_another_iframe_and_remove() {
info("Clicking on the button in the first iframe");
BrowserTestUtils.synthesizeMouse("button", 0, 0, {}, firstFrame);

info("Waiting for dialog");
await BrowserTestUtils.waitForCondition(
() => !!document.querySelector(".printPreviewBrowser")
);
await new PrintHelper(browser).waitForDialog();

isnot(
document.querySelector(".printPreviewBrowser"),
@@ -201,10 +193,7 @@ add_task(async function test_window_print_coop_site() {
"There shouldn't be any print preview browser"
);
await BrowserTestUtils.withNewTab(url, async function(browser) {
info("Waiting for dialog");
await BrowserTestUtils.waitForCondition(
() => !!document.querySelector(".printPreviewBrowser")
);
await new PrintHelper(browser).waitForDialog();

ok(true, "Shouldn't crash");
gBrowser.getTabDialogBox(browser).abortAllDialogs();
@@ -223,11 +212,7 @@ add_task(async function test_window_print_iframe_remove_on_afterprint() {
await BrowserTestUtils.withNewTab(
`${TEST_PATH}file_window_print_iframe_remove_on_afterprint.html`,
async function(browser) {
info("Waiting for dialog");
await BrowserTestUtils.waitForCondition(
() => !!document.querySelector(".printPreviewBrowser")
);

await new PrintHelper(browser).waitForDialog();
let modalBefore = await SpecialPowers.spawn(browser, [], () => {
return content.windowUtils.isInModalState();
});
@@ -295,3 +280,36 @@ add_task(async function test_focused_browsing_context() {
BrowserTestUtils.removeTab(gBrowser.selectedTab);
BrowserTestUtils.removeTab(gBrowser.selectedTab);
});

add_task(async function test_print_with_oop_iframe() {
// window.print() only shows print preview when print.tab_modal.enabled is
// true.
await SpecialPowers.pushPrefEnv({
set: [["print.tab_modal.enabled", true]],
});

is(
document.querySelector(".printPreviewBrowser"),
null,
"There shouldn't be any print preview browser"
);

await BrowserTestUtils.withNewTab(
`${TEST_PATH}file_window_print_oop_iframe.html`,
async function(browser) {
info(
"Waiting for window.print() to run and ensure we're showing the preview..."
);

let helper = new PrintHelper(browser);
await helper.waitForDialog();

isnot(
document.querySelector(".printPreviewBrowser"),
null,
"Should open the print preview correctly"
);
gBrowser.getTabDialogBox(browser).abortAllDialogs();
}
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<!doctype html>
<iframe src="https://example.com/document-builder.sjs?html=PASS"></iframe>
<script>
onload = function() {
window.print();
};
</script>
68 changes: 66 additions & 2 deletions toolkit/components/printing/tests/head.js
Original file line number Diff line number Diff line change
@@ -134,8 +134,10 @@ class PrintHelper {

if (Object.keys(condition).length === 0) {
await this.win._initialized;
// Wait a frame so the rendering spinner is hidden.
await new Promise(resolve => requestAnimationFrame(resolve));
} else if (condition.waitFor == "loadComplete") {
await BrowserTestUtils.waitForAttributeRemoval("loading", document.body);
await BrowserTestUtils.waitForAttributeRemoval("loading", this.doc.body);
}
}

@@ -328,6 +330,18 @@ class PrintHelper {
);
}

get paginationElem() {
return this.dialog._box.querySelector(".printPreviewNavigation");
}

get paginationSheetIndicator() {
return this.paginationElem.shadowRoot.querySelector("#sheetIndicator");
}

get currentPrintPreviewBrowser() {
return this.win.PrintEventHandler.printPreviewEl.lastPreviewBrowser;
}

get _printBrowser() {
return this.dialog._frame;
}
@@ -349,7 +363,34 @@ class PrintHelper {
}

get sourceURI() {
return this.win.PrintEventHandler.originalSourceCurrentURI;
return this.win.PrintEventHandler.activeCurrentURI;
}

async waitForReaderModeReady() {
if (gBrowser.selectedBrowser.isArticle) {
return;
}
await new Promise(resolve => {
let onReaderModeChange = {
receiveMessage(message) {
if (
message.data &&
message.data.isArticle !== undefined &&
gBrowser.selectedBrowser.isArticle
) {
AboutReaderParent.removeMessageListener(
"Reader:UpdateReaderButton",
onReaderModeChange
);
resolve();
}
},
};
AboutReaderParent.addMessageListener(
"Reader:UpdateReaderButton",
onReaderModeChange
);
});
}

async waitForPreview(changeFn) {
@@ -434,6 +475,22 @@ class PrintHelper {
}
}

get _lastPrintPreviewSettings() {
return this.win.PrintEventHandler._lastPrintPreviewSettings;
}

assertPreviewedWithSettings(expected) {
let settings = this._lastPrintPreviewSettings;
ok(settings, "Last preview settings are available");
for (let [setting, value] of Object.entries(expected)) {
this._assertMatches(
settings[setting],
value,
`${setting} matches previewed setting`
);
}
}

async assertSettingsChanged(from, to, changeFn) {
is(
Object.keys(from).length,
@@ -484,3 +541,10 @@ class PrintHelper {
return file;
}
}

function waitForPreviewVisible() {
return BrowserTestUtils.waitForCondition(function() {
let preview = document.querySelector(".printPreviewBrowser");
return preview && BrowserTestUtils.is_visible(preview);
});
}
16 changes: 15 additions & 1 deletion toolkit/locales/en-US/toolkit/printing/printUI.ftl
Original file line number Diff line number Diff line change
@@ -57,7 +57,21 @@ printui-two-sided-printing-short-edge = Flip on short edge
printui-options = Options
printui-headers-footers-checkbox = Print headers and footers
printui-backgrounds-checkbox = Print backgrounds
printui-selection-checkbox = Print selection only
## The "Format" section, select a version of the website to print. Radio
## options to select between the original page, selected text only, or a version
## where the page is processed with "Reader View".

# The section title.
printui-source-label = Format
# Option for printing the original page.
printui-source-radio = Original
# Option for printing just the content a user selected prior to printing.
printui-selection-radio = Selection
# Option for "simplifying" the page by printing the Reader View version.
printui-simplify-page-radio = Simplified
##

printui-color-mode-label = Color mode
printui-color-mode-color = Color

0 comments on commit b8e7c50

Please sign in to comment.