Bug 1705757 - Make printing a single frame choose the right process for the preview frame. r=nika

We were using the top BrowsingContextGroup id in this case, which is
obviously wrong. Also make the API take a BrowsingContext directly,
rather than passing outerwindowids around.

Differential Revision: https://phabricator.services.mozilla.com/D112413
This commit is contained in:
Emilio Cobos Álvarez 2021-04-17 18:41:11 +00:00
parent 9afefdd884
commit d14a43f487
8 changed files with 62 additions and 56 deletions

View File

@ -3253,8 +3253,8 @@ void nsFrameLoader::RequestSHistoryUpdate(bool aImmediately) {
}
already_AddRefed<Promise> nsFrameLoader::PrintPreview(
nsIPrintSettings* aPrintSettings,
const Optional<uint64_t>& aSourceOuterWindowID, ErrorResult& aRv) {
nsIPrintSettings* aPrintSettings, BrowsingContext* aSourceBrowsingContext,
ErrorResult& aRv) {
auto* ownerDoc = GetOwnerDoc();
if (!ownerDoc) {
aRv.ThrowNotSupportedError("No owner document");
@ -3299,11 +3299,7 @@ already_AddRefed<Promise> nsFrameLoader::PrintPreview(
return promise.forget();
}
auto winID(aSourceOuterWindowID.WasPassed()
? Some(aSourceOuterWindowID.Value())
: Nothing());
browserParent->SendPrintPreview(printData, winID)
browserParent->SendPrintPreview(printData, aSourceBrowsingContext)
->Then(
GetMainThreadSerialEventTarget(), __func__, std::move(resolve),
[promise](const mozilla::ipc::ResponseRejectReason) {
@ -3314,9 +3310,9 @@ already_AddRefed<Promise> nsFrameLoader::PrintPreview(
}
RefPtr<nsGlobalWindowOuter> sourceWindow;
if (aSourceOuterWindowID.WasPassed()) {
if (aSourceBrowsingContext) {
sourceWindow =
nsGlobalWindowOuter::GetOuterWindowWithId(aSourceOuterWindowID.Value());
nsGlobalWindowOuter::Cast(aSourceBrowsingContext->GetDOMWindow());
} else {
auto* ourDocshell = static_cast<nsDocShell*>(GetExistingDocShell());
if (NS_WARN_IF(!ourDocshell)) {
@ -3331,7 +3327,7 @@ already_AddRefed<Promise> nsFrameLoader::PrintPreview(
}
nsIDocShell* docShellToCloneInto = nullptr;
if (aSourceOuterWindowID.WasPassed()) {
if (aSourceBrowsingContext) {
// We're going to call `Print()` below on a window that is not our own,
// which happens when we are creating a new print preview document instead
// of just applying a settings change to the existing PP document. In this

View File

@ -229,9 +229,8 @@ class nsFrameLoader final : public nsStubMutationObserver,
void RequestSHistoryUpdate(bool aImmediately = false);
already_AddRefed<Promise> PrintPreview(
nsIPrintSettings* aPrintSettings,
const mozilla::dom::Optional<uint64_t>& aSourceOuterWindowID,
already_AddRefed<Promise> PrintPreview(nsIPrintSettings* aPrintSettings,
BrowsingContext* aSourceBC,
mozilla::ErrorResult& aRv);
void ExitPrintPreview();

View File

@ -124,16 +124,19 @@ interface FrameLoader {
*
* @param aPrintSettings The print settings to use to layout the print
* preview document.
* @param aSourceOuterWindowID Optionally, the ID of the nsGlobalWindowOuter
* that contains the document from which the print preview is to be
* generated. This should only be passed on the first call. It should not
* be passed for any subsequent calls that are made to update the existing
* print preview document with a new print settings object.
* @param aSourceBrowsingContext Optionally, the browsing context that
* contains the document from which the print preview is to be generated,
* which must be in the same process as the browsing context of the frame
* loader itself.
*
* This should only be passed on the first call. It should not be passed
* for any subsequent calls that are made to update the existing print
* preview document with a new print settings object.
* @return A Promise that resolves with a PrintPreviewSuccessInfo on success.
*/
[ChromeOnly, Throws]
Promise<unsigned long> printPreview(nsIPrintSettings aPrintSettings,
optional unsigned long long aSourceOuterWindowID);
BrowsingContext? aSourceBrowsingContext);
/**
* Inform the print preview document that we're done with it.

View File

@ -2302,8 +2302,7 @@ mozilla::ipc::IPCResult BrowserChild::RecvHandleAccessKey(
}
mozilla::ipc::IPCResult BrowserChild::RecvPrintPreview(
const PrintData& aPrintData,
const mozilla::Maybe<uint64_t>& aSourceOuterWindowID,
const PrintData& aPrintData, const MaybeDiscardedBrowsingContext& aSourceBC,
PrintPreviewResolver&& aCallback) {
#ifdef NS_PRINTING
// If we didn't succeed in passing off ownership of aCallback, then something
@ -2315,10 +2314,13 @@ mozilla::ipc::IPCResult BrowserChild::RecvPrintPreview(
}
});
if (NS_WARN_IF(aSourceBC.IsDiscarded())) {
return IPC_OK();
}
RefPtr<nsGlobalWindowOuter> sourceWindow;
if (aSourceOuterWindowID) {
sourceWindow =
nsGlobalWindowOuter::GetOuterWindowWithId(aSourceOuterWindowID.value());
if (!aSourceBC.IsNull()) {
sourceWindow = nsGlobalWindowOuter::Cast(aSourceBC.get()->GetDOMWindow());
if (NS_WARN_IF(!sourceWindow)) {
return IPC_OK();
}
@ -2343,7 +2345,7 @@ mozilla::ipc::IPCResult BrowserChild::RecvPrintPreview(
printSettingsSvc->DeserializeToPrintSettings(aPrintData, printSettings);
nsCOMPtr<nsIDocShell> docShellToCloneInto;
if (aSourceOuterWindowID) {
if (!aSourceBC.IsNull()) {
docShellToCloneInto = do_GetInterface(WebNavigation());
if (NS_WARN_IF(!docShellToCloneInto)) {
return IPC_OK();
@ -2371,11 +2373,14 @@ mozilla::ipc::IPCResult BrowserChild::RecvExitPrintPreview() {
return IPC_OK();
}
mozilla::ipc::IPCResult BrowserChild::RecvPrint(const uint64_t& aOuterWindowID,
const PrintData& aPrintData) {
mozilla::ipc::IPCResult BrowserChild::RecvPrint(
const MaybeDiscardedBrowsingContext& aBc, const PrintData& aPrintData) {
#ifdef NS_PRINTING
if (NS_WARN_IF(aBc.IsNullOrDiscarded())) {
return IPC_OK();
}
RefPtr<nsGlobalWindowOuter> outerWindow =
nsGlobalWindowOuter::GetOuterWindowWithId(aOuterWindowID);
nsGlobalWindowOuter::Cast(aBc.get()->GetDOMWindow());
if (NS_WARN_IF(!outerWindow)) {
return IPC_OK();
}

View File

@ -545,9 +545,8 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
mozilla::ipc::IPCResult RecvHandleAccessKey(const WidgetKeyboardEvent& aEvent,
nsTArray<uint32_t>&& aCharCodes);
mozilla::ipc::IPCResult RecvPrintPreview(
const PrintData& aPrintData,
const mozilla::Maybe<uint64_t>& aSourceOuterWindowID,
mozilla::ipc::IPCResult RecvPrintPreview(const PrintData& aPrintData,
const MaybeDiscardedBrowsingContext&,
PrintPreviewResolver&& aCallback);
mozilla::ipc::IPCResult RecvExitPrintPreview();

View File

@ -965,14 +965,14 @@ child:
*
* @param aPrintData The serialized print settings to use to layout the
* print preview document.
* @param aSourceOuterWindowID Optionally, the ID of the nsGlobalWindowOuter
* that contains the document from which the print preview is to be
* generated. This should only be passed on the first call. It should
* not be passed for any subsequent calls that are made to update the
* existing print preview document with a new print settings object.
* @param aSourceBrowsingContext Optionally, the browsing context that
* contains the document from which the print preview is to be generated.
* This should only be passed on the first call. It should not be passed
* for any subsequent calls that are made to update the existing print
* preview document with a new print settings object.
*/
async PrintPreview(PrintData aPrintData,
uint64_t? aSourceOuterWindowID) returns (PrintPreviewResultInfo aInfo);
MaybeDiscardedBrowsingContext aSourceBrowsingContext) returns (PrintPreviewResultInfo aInfo);
/**
* Inform the print preview document that we're done with it.

View File

@ -163,16 +163,22 @@ var PrintEventHandler = {
// is initiated and the print preview clone must be a snapshot from the
// time that the print was started.
let sourceBrowsingContext = this.getSourceBrowsingContext();
let args = window.arguments[0];
this.printFrameOnly = args.getProperty("printFrameOnly");
({
previewBrowser: this.previewBrowser,
selectionPreviewBrowser: this.selectionPreviewBrowser,
} = PrintUtils.createPreviewBrowsers(sourceBrowsingContext, ourBrowser));
} = PrintUtils.createPreviewBrowsers(
sourceBrowsingContext,
ourBrowser,
this.printFrameOnly
));
let args = window.arguments[0];
this.printSelectionOnly = args.getProperty("printSelectionOnly");
this.hasSelection =
args.getProperty("hasSelection") && this.selectionPreviewBrowser;
this.printFrameOnly = args.getProperty("printFrameOnly");
// Get the temporary browser that will previously have been created for the
// platform code to generate the static clone printing doc into if this
// print is for a window.print() call. In that case we steal the browser's
@ -195,12 +201,10 @@ var PrintEventHandler = {
this.originalSourceCurrentURI =
sourceBrowsingContext.currentWindowContext.documentURI.spec;
this.sourceWindowId = this.printFrameOnly
? sourceBrowsingContext.currentWindowGlobal.outerWindowId
: sourceBrowsingContext.top.embedderElement.browsingContext
.currentWindowGlobal.outerWindowId;
this.selectionWindowId =
sourceBrowsingContext.currentWindowGlobal.outerWindowId;
this.nonSelectionBrowsingContextId = this.printFrameOnly
? sourceBrowsingContext.id
: sourceBrowsingContext.top.id;
this.selectionBrowsingContextId = sourceBrowsingContext.id;
// We don't need the sourceBrowsingContext anymore, get rid of it.
sourceBrowsingContext = undefined;
@ -775,14 +779,14 @@ var PrintEventHandler = {
this._showRenderingIndicator();
let sourceWinId;
let sourceBCId;
// If it's the first time loading this type of browser, get the stored window id.
if (printSelectionOnly && !this._hasRenderedSelectionPreview) {
sourceWinId = this.selectionWindowId;
sourceBCId = this.selectionBrowsingContextId;
this._hasRenderedSelectionPreview = true;
} else if (!printSelectionOnly && !this._hasRenderedPrimaryPreview) {
sourceWinId = this.sourceWindowId;
sourceBCId = this.nonSelectionBrowsingContextId;
this._hasRenderedPrimaryPreview = true;
}
@ -817,7 +821,7 @@ var PrintEventHandler = {
isEmpty,
} = await this.currentPreviewBrowser.frameLoader.printPreview(
settings,
sourceWinId
sourceBCId ? BrowsingContext.get(sourceBCId) : null
));
} catch (e) {
this.reportPrintingError("PRINT_PREVIEW");

View File

@ -143,12 +143,12 @@ var PrintUtils = {
}
},
createPreviewBrowsers(aBrowsingContext, aDialogBrowser) {
createPreviewBrowsers(aBrowsingContext, aDialogBrowser, aPrintFrameOnly) {
let _createPreviewBrowser = previewType => {
// When we're not previewing the selection we want to make
// sure that the top-level browser is being printed.
// When we're not previewing the selection or printing only the frame, we
// want to make sure that the top-level browser is being printed.
let browsingContext =
previewType == "selection"
previewType == "selection" || aPrintFrameOnly
? aBrowsingContext
: aBrowsingContext.top.embedderElement.browsingContext;
let browser = gBrowser.createBrowser({