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

View File

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

View File

@@ -124,16 +124,19 @@ interface FrameLoader {
* *
* @param aPrintSettings The print settings to use to layout the print * @param aPrintSettings The print settings to use to layout the print
* preview document. * preview document.
* @param aSourceOuterWindowID Optionally, the ID of the nsGlobalWindowOuter * @param aSourceBrowsingContext Optionally, the browsing context that
* that contains the document from which the print preview is to be * contains the document from which the print preview is to be generated,
* generated. This should only be passed on the first call. It should not * which must be in the same process as the browsing context of the frame
* be passed for any subsequent calls that are made to update the existing * loader itself.
* print preview document with a new print settings object. *
* 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. * @return A Promise that resolves with a PrintPreviewSuccessInfo on success.
*/ */
[ChromeOnly, Throws] [ChromeOnly, Throws]
Promise<unsigned long> printPreview(nsIPrintSettings aPrintSettings, Promise<unsigned long> printPreview(nsIPrintSettings aPrintSettings,
optional unsigned long long aSourceOuterWindowID); BrowsingContext? aSourceBrowsingContext);
/** /**
* Inform the print preview document that we're done with it. * 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( mozilla::ipc::IPCResult BrowserChild::RecvPrintPreview(
const PrintData& aPrintData, const PrintData& aPrintData, const MaybeDiscardedBrowsingContext& aSourceBC,
const mozilla::Maybe<uint64_t>& aSourceOuterWindowID,
PrintPreviewResolver&& aCallback) { PrintPreviewResolver&& aCallback) {
#ifdef NS_PRINTING #ifdef NS_PRINTING
// If we didn't succeed in passing off ownership of aCallback, then something // 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; RefPtr<nsGlobalWindowOuter> sourceWindow;
if (aSourceOuterWindowID) { if (!aSourceBC.IsNull()) {
sourceWindow = sourceWindow = nsGlobalWindowOuter::Cast(aSourceBC.get()->GetDOMWindow());
nsGlobalWindowOuter::GetOuterWindowWithId(aSourceOuterWindowID.value());
if (NS_WARN_IF(!sourceWindow)) { if (NS_WARN_IF(!sourceWindow)) {
return IPC_OK(); return IPC_OK();
} }
@@ -2343,7 +2345,7 @@ mozilla::ipc::IPCResult BrowserChild::RecvPrintPreview(
printSettingsSvc->DeserializeToPrintSettings(aPrintData, printSettings); printSettingsSvc->DeserializeToPrintSettings(aPrintData, printSettings);
nsCOMPtr<nsIDocShell> docShellToCloneInto; nsCOMPtr<nsIDocShell> docShellToCloneInto;
if (aSourceOuterWindowID) { if (!aSourceBC.IsNull()) {
docShellToCloneInto = do_GetInterface(WebNavigation()); docShellToCloneInto = do_GetInterface(WebNavigation());
if (NS_WARN_IF(!docShellToCloneInto)) { if (NS_WARN_IF(!docShellToCloneInto)) {
return IPC_OK(); return IPC_OK();
@@ -2371,11 +2373,14 @@ mozilla::ipc::IPCResult BrowserChild::RecvExitPrintPreview() {
return IPC_OK(); return IPC_OK();
} }
mozilla::ipc::IPCResult BrowserChild::RecvPrint(const uint64_t& aOuterWindowID, mozilla::ipc::IPCResult BrowserChild::RecvPrint(
const PrintData& aPrintData) { const MaybeDiscardedBrowsingContext& aBc, const PrintData& aPrintData) {
#ifdef NS_PRINTING #ifdef NS_PRINTING
if (NS_WARN_IF(aBc.IsNullOrDiscarded())) {
return IPC_OK();
}
RefPtr<nsGlobalWindowOuter> outerWindow = RefPtr<nsGlobalWindowOuter> outerWindow =
nsGlobalWindowOuter::GetOuterWindowWithId(aOuterWindowID); nsGlobalWindowOuter::Cast(aBc.get()->GetDOMWindow());
if (NS_WARN_IF(!outerWindow)) { if (NS_WARN_IF(!outerWindow)) {
return IPC_OK(); return IPC_OK();
} }

View File

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

View File

@@ -965,14 +965,14 @@ child:
* *
* @param aPrintData The serialized print settings to use to layout the * @param aPrintData The serialized print settings to use to layout the
* print preview document. * print preview document.
* @param aSourceOuterWindowID Optionally, the ID of the nsGlobalWindowOuter * @param aSourceBrowsingContext Optionally, the browsing context that
* that contains the document from which the print preview is to be * contains the document from which the print preview is to be generated.
* generated. This should only be passed on the first call. It should * This should only be passed on the first call. It should not be passed
* not be passed for any subsequent calls that are made to update the * for any subsequent calls that are made to update the existing print
* existing print preview document with a new print settings object. * preview document with a new print settings object.
*/ */
async PrintPreview(PrintData aPrintData, 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. * 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 // is initiated and the print preview clone must be a snapshot from the
// time that the print was started. // time that the print was started.
let sourceBrowsingContext = this.getSourceBrowsingContext(); let sourceBrowsingContext = this.getSourceBrowsingContext();
let args = window.arguments[0];
this.printFrameOnly = args.getProperty("printFrameOnly");
({ ({
previewBrowser: this.previewBrowser, previewBrowser: this.previewBrowser,
selectionPreviewBrowser: this.selectionPreviewBrowser, selectionPreviewBrowser: this.selectionPreviewBrowser,
} = PrintUtils.createPreviewBrowsers(sourceBrowsingContext, ourBrowser)); } = PrintUtils.createPreviewBrowsers(
sourceBrowsingContext,
ourBrowser,
this.printFrameOnly
));
let args = window.arguments[0];
this.printSelectionOnly = args.getProperty("printSelectionOnly"); this.printSelectionOnly = args.getProperty("printSelectionOnly");
this.hasSelection = this.hasSelection =
args.getProperty("hasSelection") && this.selectionPreviewBrowser; args.getProperty("hasSelection") && this.selectionPreviewBrowser;
this.printFrameOnly = args.getProperty("printFrameOnly");
// Get the temporary browser that will previously have been created for the // Get the temporary browser that will previously have been created for the
// platform code to generate the static clone printing doc into if this // 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 // print is for a window.print() call. In that case we steal the browser's
@@ -195,12 +201,10 @@ var PrintEventHandler = {
this.originalSourceCurrentURI = this.originalSourceCurrentURI =
sourceBrowsingContext.currentWindowContext.documentURI.spec; sourceBrowsingContext.currentWindowContext.documentURI.spec;
this.sourceWindowId = this.printFrameOnly this.nonSelectionBrowsingContextId = this.printFrameOnly
? sourceBrowsingContext.currentWindowGlobal.outerWindowId ? sourceBrowsingContext.id
: sourceBrowsingContext.top.embedderElement.browsingContext : sourceBrowsingContext.top.id;
.currentWindowGlobal.outerWindowId; this.selectionBrowsingContextId = sourceBrowsingContext.id;
this.selectionWindowId =
sourceBrowsingContext.currentWindowGlobal.outerWindowId;
// We don't need the sourceBrowsingContext anymore, get rid of it. // We don't need the sourceBrowsingContext anymore, get rid of it.
sourceBrowsingContext = undefined; sourceBrowsingContext = undefined;
@@ -775,14 +779,14 @@ var PrintEventHandler = {
this._showRenderingIndicator(); this._showRenderingIndicator();
let sourceWinId; let sourceBCId;
// If it's the first time loading this type of browser, get the stored window id. // If it's the first time loading this type of browser, get the stored window id.
if (printSelectionOnly && !this._hasRenderedSelectionPreview) { if (printSelectionOnly && !this._hasRenderedSelectionPreview) {
sourceWinId = this.selectionWindowId; sourceBCId = this.selectionBrowsingContextId;
this._hasRenderedSelectionPreview = true; this._hasRenderedSelectionPreview = true;
} else if (!printSelectionOnly && !this._hasRenderedPrimaryPreview) { } else if (!printSelectionOnly && !this._hasRenderedPrimaryPreview) {
sourceWinId = this.sourceWindowId; sourceBCId = this.nonSelectionBrowsingContextId;
this._hasRenderedPrimaryPreview = true; this._hasRenderedPrimaryPreview = true;
} }
@@ -817,7 +821,7 @@ var PrintEventHandler = {
isEmpty, isEmpty,
} = await this.currentPreviewBrowser.frameLoader.printPreview( } = await this.currentPreviewBrowser.frameLoader.printPreview(
settings, settings,
sourceWinId sourceBCId ? BrowsingContext.get(sourceBCId) : null
)); ));
} catch (e) { } catch (e) {
this.reportPrintingError("PRINT_PREVIEW"); this.reportPrintingError("PRINT_PREVIEW");

View File

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