2018-07-30 08:05:14 +03:00
|
|
|
/* vim: set ts=2 sw=2 sts=2 et tw=80: */
|
2018-05-26 04:22:09 +03:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2018-07-30 08:05:14 +03:00
|
|
|
"use strict";
|
2018-05-26 04:22:09 +03:00
|
|
|
|
2018-07-30 08:05:14 +03:00
|
|
|
var EXPORTED_SYMBOLS = ["PrintingChild"];
|
2018-05-26 04:22:09 +03:00
|
|
|
|
2019-01-17 21:18:31 +03:00
|
|
|
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
2018-05-26 04:22:09 +03:00
|
|
|
|
2019-12-11 16:37:51 +03:00
|
|
|
ChromeUtils.defineModuleGetter(
|
|
|
|
this,
|
|
|
|
"setTimeout",
|
|
|
|
"resource://gre/modules/Timer.jsm"
|
|
|
|
);
|
|
|
|
|
2018-05-26 04:22:09 +03:00
|
|
|
ChromeUtils.defineModuleGetter(
|
|
|
|
this,
|
|
|
|
"ReaderMode",
|
|
|
|
"resource://gre/modules/ReaderMode.jsm"
|
|
|
|
);
|
|
|
|
|
2020-12-09 23:56:28 +03:00
|
|
|
ChromeUtils.defineModuleGetter(
|
|
|
|
this,
|
|
|
|
"DeferredTask",
|
|
|
|
"resource://gre/modules/DeferredTask.jsm"
|
|
|
|
);
|
|
|
|
|
2020-10-28 22:19:52 +03:00
|
|
|
let gPrintPreviewInitializingInfo = null;
|
|
|
|
|
|
|
|
let gPendingPreviewsMap = new Map();
|
|
|
|
|
|
|
|
class PrintingChild extends JSWindowActorChild {
|
|
|
|
actorCreated() {
|
|
|
|
// When the print preview page is loaded, the actor will change, so update
|
|
|
|
// the state/progress listener to the new actor.
|
|
|
|
let listener = gPendingPreviewsMap.get(this.browsingContext.id);
|
|
|
|
if (listener) {
|
|
|
|
listener.actor = this;
|
|
|
|
}
|
2020-12-09 23:56:28 +03:00
|
|
|
this.contentWindow.addEventListener("scroll", this);
|
|
|
|
}
|
|
|
|
|
|
|
|
didDestroy() {
|
|
|
|
this._scrollTask?.disarm();
|
|
|
|
this.contentWindow?.removeEventListener("scroll", this);
|
2020-10-28 22:19:52 +03:00
|
|
|
}
|
|
|
|
|
2018-05-26 04:22:09 +03:00
|
|
|
// Bug 1088061: nsPrintJob's DoCommonPrint currently expects the
|
|
|
|
// progress listener passed to it to QI to an nsIPrintingPromptService
|
|
|
|
// in order to know that a printing progress dialog has been shown. That's
|
|
|
|
// really all the interface is used for, hence the fact that I don't actually
|
|
|
|
// implement the interface here. Bug 1088061 has been filed to remove
|
|
|
|
// this hackery.
|
|
|
|
|
|
|
|
get shouldSavePrintSettings() {
|
2020-02-14 05:59:45 +03:00
|
|
|
return Services.prefs.getBoolPref("print.save_print_settings");
|
2018-07-30 08:05:14 +03:00
|
|
|
}
|
2018-05-26 04:22:09 +03:00
|
|
|
|
2018-07-30 08:05:14 +03:00
|
|
|
handleEvent(event) {
|
2018-05-26 04:22:09 +03:00
|
|
|
switch (event.type) {
|
|
|
|
case "PrintingError": {
|
|
|
|
let win = event.target.defaultView;
|
2018-08-02 22:26:47 +03:00
|
|
|
let wbp = win.getInterface(Ci.nsIWebBrowserPrint);
|
2018-05-26 04:22:09 +03:00
|
|
|
let nsresult = event.detail;
|
2020-10-28 22:19:52 +03:00
|
|
|
this.sendAsyncMessage("Printing:Error", {
|
2018-05-26 04:22:09 +03:00
|
|
|
isPrinting: wbp.doingPrint,
|
|
|
|
nsresult,
|
|
|
|
});
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case "printPreviewUpdate": {
|
2020-10-28 22:19:52 +03:00
|
|
|
let info = gPrintPreviewInitializingInfo;
|
2018-05-26 04:22:09 +03:00
|
|
|
if (!info) {
|
2020-10-28 22:19:52 +03:00
|
|
|
// If there is no gPrintPreviewInitializingInfo then we did not
|
2018-05-26 04:22:09 +03:00
|
|
|
// initiate the preview so ignore this event.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only send Printing:Preview:Entered message on first update, indicated
|
2020-10-28 22:19:52 +03:00
|
|
|
// by gPrintPreviewInitializingInfo.entered not being set.
|
2018-05-26 04:22:09 +03:00
|
|
|
if (!info.entered) {
|
2020-10-28 22:19:52 +03:00
|
|
|
gPendingPreviewsMap.delete(this.browsingContext.id);
|
|
|
|
|
2018-05-26 04:22:09 +03:00
|
|
|
info.entered = true;
|
2020-10-28 22:19:52 +03:00
|
|
|
this.sendAsyncMessage("Printing:Preview:Entered", {
|
2018-05-26 04:22:09 +03:00
|
|
|
failed: false,
|
|
|
|
changingBrowsers: info.changingBrowsers,
|
|
|
|
});
|
|
|
|
|
|
|
|
// If we have another request waiting, dispatch it now.
|
|
|
|
if (info.nextRequest) {
|
|
|
|
Services.tm.dispatchToMainThread(info.nextRequest);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Always send page count update.
|
2020-10-28 22:19:52 +03:00
|
|
|
this.updatePageCount();
|
2018-05-26 04:22:09 +03:00
|
|
|
break;
|
|
|
|
}
|
2020-12-09 23:56:28 +03:00
|
|
|
|
|
|
|
case "scroll":
|
|
|
|
if (!this._scrollTask) {
|
|
|
|
this._scrollTask = new DeferredTask(
|
|
|
|
() => this.updateCurrentPage(),
|
|
|
|
16,
|
|
|
|
16
|
|
|
|
);
|
|
|
|
}
|
|
|
|
this._scrollTask.arm();
|
|
|
|
break;
|
2018-05-26 04:22:09 +03:00
|
|
|
}
|
2018-07-30 08:05:14 +03:00
|
|
|
}
|
2018-05-26 04:22:09 +03:00
|
|
|
|
2018-07-30 08:05:14 +03:00
|
|
|
receiveMessage(message) {
|
2018-05-26 04:22:09 +03:00
|
|
|
let data = message.data;
|
|
|
|
switch (message.name) {
|
|
|
|
case "Printing:Preview:Enter": {
|
2018-07-30 08:05:14 +03:00
|
|
|
this.enterPrintPreview(
|
2020-08-19 12:27:18 +03:00
|
|
|
BrowsingContext.get(data.browsingContextId),
|
2018-05-26 04:22:09 +03:00
|
|
|
data.simplifiedMode,
|
|
|
|
data.changingBrowsers,
|
2020-11-07 19:01:57 +03:00
|
|
|
data.lastUsedPrinterName
|
2018-05-26 04:22:09 +03:00
|
|
|
);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case "Printing:Preview:Exit": {
|
2018-07-30 08:05:14 +03:00
|
|
|
this.exitPrintPreview();
|
2018-05-26 04:22:09 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case "Printing:Preview:Navigate": {
|
2018-07-30 08:05:14 +03:00
|
|
|
this.navigate(data.navType, data.pageNum);
|
2018-05-26 04:22:09 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case "Printing:Preview:ParseDocument": {
|
2020-10-28 22:19:52 +03:00
|
|
|
return this.parseDocument(
|
2018-07-30 08:05:14 +03:00
|
|
|
data.URL,
|
|
|
|
Services.wm.getOuterWindowWithId(data.windowID)
|
|
|
|
);
|
2018-05-26 04:22:09 +03:00
|
|
|
}
|
|
|
|
}
|
2020-10-28 22:19:52 +03:00
|
|
|
|
|
|
|
return undefined;
|
2018-07-30 08:05:14 +03:00
|
|
|
}
|
2018-05-26 04:22:09 +03:00
|
|
|
|
2020-05-29 20:37:01 +03:00
|
|
|
getPrintSettings(lastUsedPrinterName) {
|
2018-05-26 04:22:09 +03:00
|
|
|
try {
|
|
|
|
let PSSVC = Cc["@mozilla.org/gfx/printsettings-service;1"].getService(
|
|
|
|
Ci.nsIPrintSettingsService
|
|
|
|
);
|
|
|
|
|
2020-09-30 15:25:02 +03:00
|
|
|
let printSettings = PSSVC.newPrintSettings;
|
2018-05-26 04:22:09 +03:00
|
|
|
if (!printSettings.printerName) {
|
2020-05-29 20:37:01 +03:00
|
|
|
printSettings.printerName = lastUsedPrinterName;
|
2018-05-26 04:22:09 +03:00
|
|
|
}
|
|
|
|
// First get any defaults from the printer
|
|
|
|
PSSVC.initPrintSettingsFromPrinter(
|
|
|
|
printSettings.printerName,
|
|
|
|
printSettings
|
|
|
|
);
|
|
|
|
// now augment them with any values from last time
|
|
|
|
PSSVC.initPrintSettingsFromPrefs(
|
|
|
|
printSettings,
|
|
|
|
true,
|
|
|
|
printSettings.kInitSaveAll
|
|
|
|
);
|
|
|
|
|
|
|
|
return printSettings;
|
|
|
|
} catch (e) {
|
|
|
|
Cu.reportError(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
2018-07-30 08:05:14 +03:00
|
|
|
}
|
2018-05-26 04:22:09 +03:00
|
|
|
|
2020-10-28 22:19:52 +03:00
|
|
|
async parseDocument(URL, contentWindow) {
|
|
|
|
// The document in 'contentWindow' will be simplified and the resulting nodes
|
|
|
|
// will be inserted into this.contentWindow.
|
|
|
|
let thisWindow = this.contentWindow;
|
|
|
|
|
2018-05-26 04:22:09 +03:00
|
|
|
// By using ReaderMode primitives, we parse given document and place the
|
|
|
|
// resulting JS object into the DOM of current browser.
|
2020-10-28 22:19:52 +03:00
|
|
|
let article;
|
|
|
|
try {
|
|
|
|
article = await ReaderMode.parseDocument(contentWindow.document);
|
|
|
|
} catch (ex) {
|
|
|
|
Cu.reportError(ex);
|
|
|
|
}
|
2020-10-28 18:32:34 +03:00
|
|
|
|
2020-10-28 22:19:52 +03:00
|
|
|
// 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");
|
|
|
|
};
|
|
|
|
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");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
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
|
|
|
|
);
|
2020-10-28 18:32:34 +03:00
|
|
|
|
2020-10-28 22:19:52 +03:00
|
|
|
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
|
2018-05-26 04:22:09 +03:00
|
|
|
);
|
|
|
|
|
2020-10-28 22:19:52 +03:00
|
|
|
readerContent.appendChild(contentFragment);
|
2018-05-26 04:22:09 +03:00
|
|
|
|
2020-10-28 22:19:52 +03:00
|
|
|
// Display reader content element
|
|
|
|
readerContent.style.display = "block";
|
|
|
|
} else {
|
|
|
|
let aboutReaderStrings = Services.strings.createBundle(
|
|
|
|
"chrome://global/locale/aboutReader.properties"
|
2018-05-26 04:22:09 +03:00
|
|
|
);
|
2020-10-28 22:19:52 +03:00
|
|
|
let errorMessage = aboutReaderStrings.GetStringFromName(
|
|
|
|
"aboutReader.loadError"
|
2018-05-26 04:22:09 +03:00
|
|
|
);
|
|
|
|
|
2020-10-28 22:19:52 +03:00
|
|
|
document.title = errorMessage;
|
2018-05-26 04:22:09 +03:00
|
|
|
|
2020-10-28 22:19:52 +03:00
|
|
|
// 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);
|
2020-10-28 18:32:34 +03:00
|
|
|
|
2020-10-28 22:19:52 +03:00
|
|
|
// Display reader message element
|
|
|
|
readerMessageElement.style.display = "block";
|
|
|
|
}
|
2018-07-30 08:05:14 +03:00
|
|
|
}
|
2018-05-26 04:22:09 +03:00
|
|
|
|
2018-07-30 08:05:14 +03:00
|
|
|
enterPrintPreview(
|
2020-08-19 12:27:18 +03:00
|
|
|
browsingContext,
|
2018-07-30 08:05:14 +03:00
|
|
|
simplifiedMode,
|
|
|
|
changingBrowsers,
|
2020-11-07 19:01:57 +03:00
|
|
|
lastUsedPrinterName
|
2018-07-30 08:05:14 +03:00
|
|
|
) {
|
|
|
|
const { docShell } = this;
|
2020-08-19 12:27:18 +03:00
|
|
|
|
2018-05-26 04:22:09 +03:00
|
|
|
try {
|
2020-08-19 12:27:18 +03:00
|
|
|
let contentWindow = browsingContext.window;
|
2020-05-29 20:37:01 +03:00
|
|
|
let printSettings = this.getPrintSettings(lastUsedPrinterName);
|
2018-05-26 04:22:09 +03:00
|
|
|
|
2020-08-13 21:12:04 +03:00
|
|
|
// Disable the progress dialog for generating previews.
|
|
|
|
printSettings.showPrintProgress = !Services.prefs.getBoolPref(
|
|
|
|
"print.tab_modal.enabled",
|
|
|
|
false
|
|
|
|
);
|
|
|
|
|
2018-05-26 04:22:09 +03:00
|
|
|
// If we happen to be on simplified mode, we need to set docURL in order
|
|
|
|
// to generate header/footer content correctly, since simplified tab has
|
|
|
|
// "about:blank" as its URI.
|
|
|
|
if (printSettings && simplifiedMode) {
|
|
|
|
printSettings.docURL = contentWindow.document.baseURI;
|
2019-07-05 12:04:56 +03:00
|
|
|
}
|
2018-05-26 04:22:09 +03:00
|
|
|
|
2020-10-28 22:19:52 +03:00
|
|
|
// Get this early in case the actor goes away during print preview.
|
|
|
|
let browserContextId = this.browsingContext.id;
|
|
|
|
|
2018-05-26 04:22:09 +03:00
|
|
|
// The print preview docshell will be in a different TabGroup, so
|
|
|
|
// printPreviewInitialize must be run in a separate runnable to avoid
|
|
|
|
// touching a different TabGroup in our own runnable.
|
|
|
|
let printPreviewInitialize = () => {
|
2020-08-13 14:45:12 +03:00
|
|
|
// During dispatching this function to the main-thread, the docshell
|
|
|
|
// might be destroyed, for example the print preview window gets closed
|
|
|
|
// soon after it's opened, in such case we should just simply bail out.
|
|
|
|
if (docShell.isBeingDestroyed()) {
|
2020-10-28 22:19:52 +03:00
|
|
|
this.sendAsyncMessage("Printing:Preview:Entered", {
|
2020-08-13 14:45:12 +03:00
|
|
|
failed: true,
|
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
Bug 1636728 - Centralize printing entry points in nsGlobalWindowOuter, and move cloning out of nsPrintJob. r=jwatt,geckoview-reviewers,smaug,agi
This centralizes our print and preview setup in nsGlobalWindowOuter so
that we never re-clone a clone, and so that we reuse the window.open()
codepath to create the browsing context to clone into.
For window.print, for both old print dialog / silent printing and new
print preview UI, we now create a hidden browser (as in with visibility:
collapse, which takes no space but still gets a layout box).
* In the modern UI case, this browser is swapped with the actual print
preview clone, and the UI takes care of removing the browser.
* In the print dialog / silent printing case, the printing code calls
window.close() from nsDocumentViewer::OnDonePrinting().
* We don't need to care about the old print preview UI for this case
because it can't be open from window.print().
We need to fall back to an actual window when there's no
nsIBrowserDOMWindow around for WPT print tests and the like, which don't
have one. That seems fine, we could special-case this code path more if
needed but it doesn't seem worth it.
Differential Revision: https://phabricator.services.mozilla.com/D87063
2020-08-25 20:45:12 +03:00
|
|
|
|
2018-05-26 04:22:09 +03:00
|
|
|
try {
|
2020-10-28 22:19:52 +03:00
|
|
|
let listener = new PrintingListener(this);
|
|
|
|
gPendingPreviewsMap.set(browserContextId, listener);
|
|
|
|
|
|
|
|
gPrintPreviewInitializingInfo = { changingBrowsers };
|
2018-05-26 04:22:09 +03:00
|
|
|
|
Bug 1636728 - Centralize printing entry points in nsGlobalWindowOuter, and move cloning out of nsPrintJob. r=jwatt,geckoview-reviewers,smaug,agi
This centralizes our print and preview setup in nsGlobalWindowOuter so
that we never re-clone a clone, and so that we reuse the window.open()
codepath to create the browsing context to clone into.
For window.print, for both old print dialog / silent printing and new
print preview UI, we now create a hidden browser (as in with visibility:
collapse, which takes no space but still gets a layout box).
* In the modern UI case, this browser is swapped with the actual print
preview clone, and the UI takes care of removing the browser.
* In the print dialog / silent printing case, the printing code calls
window.close() from nsDocumentViewer::OnDonePrinting().
* We don't need to care about the old print preview UI for this case
because it can't be open from window.print().
We need to fall back to an actual window when there's no
nsIBrowserDOMWindow around for WPT print tests and the like, which don't
have one. That seems fine, we could special-case this code path more if
needed but it doesn't seem worth it.
Differential Revision: https://phabricator.services.mozilla.com/D87063
2020-08-25 20:45:12 +03:00
|
|
|
contentWindow.printPreview(printSettings, listener, docShell);
|
2018-05-26 04:22:09 +03:00
|
|
|
} catch (error) {
|
|
|
|
// This might fail if we, for example, attempt to print a XUL document.
|
|
|
|
// In that case, we inform the parent to bail out of print preview.
|
|
|
|
Cu.reportError(error);
|
2020-10-28 22:19:52 +03:00
|
|
|
gPrintPreviewInitializingInfo = null;
|
|
|
|
this.sendAsyncMessage("Printing:Preview:Entered", {
|
2018-07-30 08:05:14 +03:00
|
|
|
failed: true,
|
|
|
|
});
|
2018-05-26 04:22:09 +03:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-10-28 22:19:52 +03:00
|
|
|
// If gPrintPreviewInitializingInfo.entered is not set we are still in the
|
2018-05-26 04:22:09 +03:00
|
|
|
// initial setup of a previous preview request. We delay this one until
|
|
|
|
// that has finished because running them at the same time will almost
|
|
|
|
// certainly cause failures.
|
|
|
|
if (
|
2020-10-28 22:19:52 +03:00
|
|
|
gPrintPreviewInitializingInfo &&
|
|
|
|
!gPrintPreviewInitializingInfo.entered
|
2018-05-26 04:22:09 +03:00
|
|
|
) {
|
2020-10-28 22:19:52 +03:00
|
|
|
gPrintPreviewInitializingInfo.nextRequest = printPreviewInitialize;
|
2018-05-26 04:22:09 +03:00
|
|
|
} else {
|
|
|
|
Services.tm.dispatchToMainThread(printPreviewInitialize);
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
// This might fail if we, for example, attempt to print a XUL document.
|
|
|
|
// In that case, we inform the parent to bail out of print preview.
|
|
|
|
Cu.reportError(error);
|
2020-10-28 22:19:52 +03:00
|
|
|
this.sendAsyncMessage("Printing:Preview:Entered", {
|
|
|
|
failed: true,
|
|
|
|
});
|
2018-05-26 04:22:09 +03:00
|
|
|
}
|
2018-07-30 08:05:14 +03:00
|
|
|
}
|
2018-05-26 04:22:09 +03:00
|
|
|
|
2020-10-28 22:19:52 +03:00
|
|
|
exitPrintPreview() {
|
|
|
|
gPrintPreviewInitializingInfo = null;
|
Bug 1636728 - Centralize printing entry points in nsGlobalWindowOuter, and move cloning out of nsPrintJob. r=jwatt,geckoview-reviewers,smaug,agi
This centralizes our print and preview setup in nsGlobalWindowOuter so
that we never re-clone a clone, and so that we reuse the window.open()
codepath to create the browsing context to clone into.
For window.print, for both old print dialog / silent printing and new
print preview UI, we now create a hidden browser (as in with visibility:
collapse, which takes no space but still gets a layout box).
* In the modern UI case, this browser is swapped with the actual print
preview clone, and the UI takes care of removing the browser.
* In the print dialog / silent printing case, the printing code calls
window.close() from nsDocumentViewer::OnDonePrinting().
* We don't need to care about the old print preview UI for this case
because it can't be open from window.print().
We need to fall back to an actual window when there's no
nsIBrowserDOMWindow around for WPT print tests and the like, which don't
have one. That seems fine, we could special-case this code path more if
needed but it doesn't seem worth it.
Differential Revision: https://phabricator.services.mozilla.com/D87063
2020-08-25 20:45:12 +03:00
|
|
|
this.docShell.exitPrintPreview();
|
2018-07-30 08:05:14 +03:00
|
|
|
}
|
2018-05-26 04:22:09 +03:00
|
|
|
|
2018-07-30 08:05:14 +03:00
|
|
|
updatePageCount() {
|
Bug 1636728 - Centralize printing entry points in nsGlobalWindowOuter, and move cloning out of nsPrintJob. r=jwatt,geckoview-reviewers,smaug,agi
This centralizes our print and preview setup in nsGlobalWindowOuter so
that we never re-clone a clone, and so that we reuse the window.open()
codepath to create the browsing context to clone into.
For window.print, for both old print dialog / silent printing and new
print preview UI, we now create a hidden browser (as in with visibility:
collapse, which takes no space but still gets a layout box).
* In the modern UI case, this browser is swapped with the actual print
preview clone, and the UI takes care of removing the browser.
* In the print dialog / silent printing case, the printing code calls
window.close() from nsDocumentViewer::OnDonePrinting().
* We don't need to care about the old print preview UI for this case
because it can't be open from window.print().
We need to fall back to an actual window when there's no
nsIBrowserDOMWindow around for WPT print tests and the like, which don't
have one. That seems fine, we could special-case this code path more if
needed but it doesn't seem worth it.
Differential Revision: https://phabricator.services.mozilla.com/D87063
2020-08-25 20:45:12 +03:00
|
|
|
let cv = this.docShell.contentViewer;
|
|
|
|
cv.QueryInterface(Ci.nsIWebBrowserPrint);
|
2020-10-28 22:19:52 +03:00
|
|
|
this.sendAsyncMessage("Printing:Preview:UpdatePageCount", {
|
Bug 1636728 - Centralize printing entry points in nsGlobalWindowOuter, and move cloning out of nsPrintJob. r=jwatt,geckoview-reviewers,smaug,agi
This centralizes our print and preview setup in nsGlobalWindowOuter so
that we never re-clone a clone, and so that we reuse the window.open()
codepath to create the browsing context to clone into.
For window.print, for both old print dialog / silent printing and new
print preview UI, we now create a hidden browser (as in with visibility:
collapse, which takes no space but still gets a layout box).
* In the modern UI case, this browser is swapped with the actual print
preview clone, and the UI takes care of removing the browser.
* In the print dialog / silent printing case, the printing code calls
window.close() from nsDocumentViewer::OnDonePrinting().
* We don't need to care about the old print preview UI for this case
because it can't be open from window.print().
We need to fall back to an actual window when there's no
nsIBrowserDOMWindow around for WPT print tests and the like, which don't
have one. That seems fine, we could special-case this code path more if
needed but it doesn't seem worth it.
Differential Revision: https://phabricator.services.mozilla.com/D87063
2020-08-25 20:45:12 +03:00
|
|
|
numPages: cv.printPreviewNumPages,
|
2020-08-27 08:10:16 +03:00
|
|
|
totalPages: cv.rawNumPages,
|
2018-05-26 04:22:09 +03:00
|
|
|
});
|
2018-07-30 08:05:14 +03:00
|
|
|
}
|
2018-05-26 04:22:09 +03:00
|
|
|
|
2020-12-09 23:56:28 +03:00
|
|
|
updateCurrentPage() {
|
|
|
|
let cv = this.docShell.contentViewer;
|
|
|
|
cv.QueryInterface(Ci.nsIWebBrowserPrint);
|
|
|
|
this.sendAsyncMessage("Printing:Preview:CurrentPage", {
|
|
|
|
currentPage: cv.printPreviewCurrentPageNumber,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-07-30 08:05:14 +03:00
|
|
|
navigate(navType, pageNum) {
|
Bug 1636728 - Centralize printing entry points in nsGlobalWindowOuter, and move cloning out of nsPrintJob. r=jwatt,geckoview-reviewers,smaug,agi
This centralizes our print and preview setup in nsGlobalWindowOuter so
that we never re-clone a clone, and so that we reuse the window.open()
codepath to create the browsing context to clone into.
For window.print, for both old print dialog / silent printing and new
print preview UI, we now create a hidden browser (as in with visibility:
collapse, which takes no space but still gets a layout box).
* In the modern UI case, this browser is swapped with the actual print
preview clone, and the UI takes care of removing the browser.
* In the print dialog / silent printing case, the printing code calls
window.close() from nsDocumentViewer::OnDonePrinting().
* We don't need to care about the old print preview UI for this case
because it can't be open from window.print().
We need to fall back to an actual window when there's no
nsIBrowserDOMWindow around for WPT print tests and the like, which don't
have one. That seems fine, we could special-case this code path more if
needed but it doesn't seem worth it.
Differential Revision: https://phabricator.services.mozilla.com/D87063
2020-08-25 20:45:12 +03:00
|
|
|
let cv = this.docShell.contentViewer;
|
|
|
|
cv.QueryInterface(Ci.nsIWebBrowserPrint);
|
|
|
|
cv.printPreviewScrollToPage(navType, pageNum);
|
2018-07-30 08:05:14 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PrintingChild.prototype.QueryInterface = ChromeUtils.generateQI([
|
Bug 1649221: Update ChromeUtils.generateQI callers to pass strings. r=mccr8,remote-protocol-reviewers,marionette-reviewers,perftest-reviewers,webcompat-reviewers,geckoview-reviewers,preferences-reviewers,agi,whimboo,Bebe,twisniewski
Differential Revision: https://phabricator.services.mozilla.com/D81594
2020-07-11 02:58:28 +03:00
|
|
|
"nsIPrintingPromptService",
|
2018-07-30 08:05:14 +03:00
|
|
|
]);
|
2018-05-26 04:22:09 +03:00
|
|
|
|
2020-10-28 22:19:52 +03:00
|
|
|
function PrintingListener(actor) {
|
|
|
|
this.actor = actor;
|
2018-05-26 04:22:09 +03:00
|
|
|
}
|
|
|
|
PrintingListener.prototype = {
|
Bug 1649221: Update ChromeUtils.generateQI callers to pass strings. r=mccr8,remote-protocol-reviewers,marionette-reviewers,perftest-reviewers,webcompat-reviewers,geckoview-reviewers,preferences-reviewers,agi,whimboo,Bebe,twisniewski
Differential Revision: https://phabricator.services.mozilla.com/D81594
2020-07-11 02:58:28 +03:00
|
|
|
QueryInterface: ChromeUtils.generateQI(["nsIWebProgressListener"]),
|
2018-05-26 04:22:09 +03:00
|
|
|
|
|
|
|
onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
|
2020-10-28 22:19:52 +03:00
|
|
|
this.actor.sendAsyncMessage("Printing:Preview:StateChange", {
|
2018-05-26 04:22:09 +03:00
|
|
|
stateFlags: aStateFlags,
|
|
|
|
status: aStatus,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
onProgressChange(
|
|
|
|
aWebProgress,
|
|
|
|
aRequest,
|
|
|
|
aCurSelfProgress,
|
|
|
|
aMaxSelfProgress,
|
|
|
|
aCurTotalProgress,
|
|
|
|
aMaxTotalProgress
|
|
|
|
) {
|
2020-10-28 22:19:52 +03:00
|
|
|
this.actor.sendAsyncMessage("Printing:Preview:ProgressChange", {
|
2018-05-26 04:22:09 +03:00
|
|
|
curSelfProgress: aCurSelfProgress,
|
|
|
|
maxSelfProgress: aMaxSelfProgress,
|
|
|
|
curTotalProgress: aCurTotalProgress,
|
|
|
|
maxTotalProgress: aMaxTotalProgress,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
onLocationChange(aWebProgress, aRequest, aLocation, aFlags) {},
|
|
|
|
onStatusChange(aWebProgress, aRequest, aStatus, aMessage) {},
|
2018-11-29 18:46:08 +03:00
|
|
|
onSecurityChange(aWebProgress, aRequest, aState) {},
|
2019-01-07 01:45:57 +03:00
|
|
|
onContentBlockingEvent(aWebProgress, aRequest, aEvent) {},
|
2018-05-26 04:22:09 +03:00
|
|
|
};
|