Bug 1662975 - Don't return from window.print() until the print dialog is closed. r=jwatt

As much as I hate nested event loops, I think we need to do it for this
case :)

Hopefully print() already assumes nested event loops can happen because
of the native dialog so it's already properly set up for this.

Differential Revision: https://phabricator.services.mozilla.com/D89254
This commit is contained in:
Emilio Cobos Álvarez 2020-09-03 17:03:06 +00:00
Родитель 473f41370a
Коммит c0f4091be3
5 изменённых файлов: 32 добавлений и 13 удалений

Просмотреть файл

@ -3286,7 +3286,8 @@ already_AddRefed<Promise> nsFrameLoader::PrintPreview(
sourceWindow->Print(
aPrintSettings,
/* aListener = */ nullptr, docShellToCloneInto,
/* aIsPreview = */ true,
nsGlobalWindowOuter::IsPreview::Yes,
nsGlobalWindowOuter::BlockUntilDone::No,
[resolve](const PrintPreviewResultInfo& aInfo) { resolve(aInfo); }, rv);
if (NS_WARN_IF(rv.Failed())) {
promise->MaybeReject(std::move(rv));
@ -3357,7 +3358,8 @@ already_AddRefed<Promise> nsFrameLoader::Print(uint64_t aOuterWindowID,
ErrorResult rv;
outerWindow->Print(aPrintSettings, listener,
/* aDocShellToCloneInto = */ nullptr,
/* aIsPreview = */ false,
nsGlobalWindowOuter::IsPreview::No,
nsGlobalWindowOuter::BlockUntilDone::No,
/* aPrintPreviewCallback = */ nullptr, rv);
if (rv.Failed()) {
promise->MaybeReject(std::move(rv));

Просмотреть файл

@ -3613,7 +3613,8 @@ Nullable<WindowProxyHolder> nsGlobalWindowInner::PrintPreview(
nsIDocShell* aDocShellToCloneInto, ErrorResult& aError) {
FORWARD_TO_OUTER_OR_THROW(Print,
(aSettings, aListener, aDocShellToCloneInto,
/* aIsPreview = */ true,
nsGlobalWindowOuter::IsPreview::Yes,
nsGlobalWindowOuter::BlockUntilDone::No,
/* aPrintPreviewCallback = */ nullptr, aError),
aError, nullptr);
}

Просмотреть файл

@ -5274,13 +5274,15 @@ void nsGlobalWindowOuter::PrintOuter(ErrorResult& aError) {
settings->SetShowPrintProgress(false);
}
Print(settings, nullptr, nullptr, isPreview, nullptr, aError);
Print(settings, nullptr, nullptr, IsPreview(isPreview),
BlockUntilDone(isPreview), nullptr, aError);
#endif
}
Nullable<WindowProxyHolder> nsGlobalWindowOuter::Print(
nsIPrintSettings* aPrintSettings, nsIWebProgressListener* aListener,
nsIDocShell* aDocShellToCloneInto, bool aIsPreview,
nsIDocShell* aDocShellToCloneInto, IsPreview aIsPreview,
BlockUntilDone aBlockUntilDone,
PrintPreviewResolver&& aPrintPreviewCallback, ErrorResult& aError) {
#ifdef NS_PRINTING
nsCOMPtr<nsIPrintSettingsService> printSettingsService =
@ -5310,7 +5312,7 @@ Nullable<WindowProxyHolder> nsGlobalWindowOuter::Print(
nsCOMPtr<nsIContentViewer> cv;
RefPtr<BrowsingContext> bc;
if (docToPrint->IsStaticDocument() && aIsPreview) {
if (docToPrint->IsStaticDocument() && bool(aIsPreview)) {
// We're already a print preview window, just reuse our browsing context /
// content viewer.
//
@ -5337,7 +5339,8 @@ Nullable<WindowProxyHolder> nsGlobalWindowOuter::Print(
bc = aDocShellToCloneInto->GetBrowsingContext();
} else {
AutoNoJSAPI nojsapi;
auto printKind = aIsPreview ? PrintKind::PrintPreview : PrintKind::Print;
auto printKind =
bool(aIsPreview) ? PrintKind::PrintPreview : PrintKind::Print;
aError = OpenInternal(EmptyString(), EmptyString(), EmptyString(),
false, // aDialog
false, // aContentModal
@ -5438,13 +5441,22 @@ Nullable<WindowProxyHolder> nsGlobalWindowOuter::Print(
return nullptr;
}
if (aIsPreview) {
if (bool(aIsPreview)) {
aError = webBrowserPrint->PrintPreview(aPrintSettings, aListener,
std::move(aPrintPreviewCallback));
if (aError.Failed()) {
return nullptr;
}
} else {
// Historically we've eaten this error.
webBrowserPrint->Print(aPrintSettings, aListener);
}
if (bool(aBlockUntilDone)) {
// Wait until print document is closed.
SpinEventLoopUntil([&] { return bc->IsDiscarded(); });
}
return WindowProxyHolder(std::move(bc));
#else
return nullptr;

Просмотреть файл

@ -586,9 +586,11 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
void PrintOuter(mozilla::ErrorResult& aError);
enum class IsPreview : bool { No, Yes };
enum class BlockUntilDone : bool { No, Yes };
mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> Print(
nsIPrintSettings*, nsIWebProgressListener*, nsIDocShell*, bool aIsPreview,
PrintPreviewResolver&& aPrintPreviewCallback, mozilla::ErrorResult&);
nsIPrintSettings*, nsIWebProgressListener*, nsIDocShell*, IsPreview,
BlockUntilDone, PrintPreviewResolver&&, mozilla::ErrorResult&);
mozilla::dom::Selection* GetSelectionOuter();
already_AddRefed<mozilla::dom::Selection> GetSelection() override;
nsScreen* GetScreen();

Просмотреть файл

@ -2285,8 +2285,9 @@ mozilla::ipc::IPCResult BrowserChild::RecvPrintPreview(
sourceWindow->Print(printSettings,
/* aListener = */ nullptr, docShellToCloneInto,
/* aIsPreview = */ true, std::move(aCallback),
IgnoreErrors());
nsGlobalWindowOuter::IsPreview::Yes,
nsGlobalWindowOuter::BlockUntilDone::No,
std::move(aCallback), IgnoreErrors());
#endif
return IPC_OK();
}
@ -2338,7 +2339,8 @@ mozilla::ipc::IPCResult BrowserChild::RecvPrint(const uint64_t& aOuterWindowID,
outerWindow->Print(printSettings,
/* aListener = */ nullptr,
/* aWindowToCloneInto = */ nullptr,
/* aIsPreview = */ false,
nsGlobalWindowOuter::IsPreview::No,
nsGlobalWindowOuter::BlockUntilDone::No,
/* aPrintPreviewCallback = */ nullptr, rv);
if (NS_WARN_IF(rv.Failed())) {
return IPC_OK();