summaryrefslogtreecommitdiffstats
path: root/docshell/base/CanonicalBrowsingContext.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:35:49 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:35:49 +0000
commitd8bbc7858622b6d9c278469aab701ca0b609cddf (patch)
treeeff41dc61d9f714852212739e6b3738b82a2af87 /docshell/base/CanonicalBrowsingContext.cpp
parentReleasing progress-linux version 125.0.3-1~progress7.99u1. (diff)
downloadfirefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.tar.xz
firefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.zip
Merging upstream version 126.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'docshell/base/CanonicalBrowsingContext.cpp')
-rw-r--r--docshell/base/CanonicalBrowsingContext.cpp150
1 files changed, 138 insertions, 12 deletions
diff --git a/docshell/base/CanonicalBrowsingContext.cpp b/docshell/base/CanonicalBrowsingContext.cpp
index 84f2d2960a..4c92988c9b 100644
--- a/docshell/base/CanonicalBrowsingContext.cpp
+++ b/docshell/base/CanonicalBrowsingContext.cpp
@@ -6,8 +6,10 @@
#include "mozilla/dom/CanonicalBrowsingContext.h"
+#include "ContentAnalysis.h"
#include "ErrorList.h"
#include "mozilla/CheckedInt.h"
+#include "mozilla/Components.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/EventForwards.h"
#include "mozilla/AsyncEventDispatcher.h"
@@ -47,6 +49,7 @@
#include "nsFrameLoader.h"
#include "nsFrameLoaderOwner.h"
#include "nsGlobalWindowOuter.h"
+#include "nsIContentAnalysis.h"
#include "nsIWebBrowserChrome.h"
#include "nsIXULRuntime.h"
#include "nsNetUtil.h"
@@ -668,6 +671,9 @@ CanonicalBrowsingContext::ReplaceLoadingSessionHistoryEntryForLoad(
using PrintPromise = CanonicalBrowsingContext::PrintPromise;
#ifdef NS_PRINTING
+// Clients must call StaticCloneForPrintingCreated or
+// NoStaticCloneForPrintingWillBeCreated before the underlying promise can
+// resolve.
class PrintListenerAdapter final : public nsIWebProgressListener {
public:
explicit PrintListenerAdapter(PrintPromise::Private* aPromise)
@@ -678,10 +684,14 @@ class PrintListenerAdapter final : public nsIWebProgressListener {
// NS_DECL_NSIWEBPROGRESSLISTENER
NS_IMETHOD OnStateChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
uint32_t aStateFlags, nsresult aStatus) override {
+ MOZ_ASSERT(NS_IsMainThread());
if (aStateFlags & nsIWebProgressListener::STATE_STOP &&
aStateFlags & nsIWebProgressListener::STATE_IS_DOCUMENT && mPromise) {
- mPromise->Resolve(true, __func__);
- mPromise = nullptr;
+ mPrintJobFinished = true;
+ if (mHaveSetBrowsingContext) {
+ mPromise->Resolve(mClonedStaticBrowsingContext, __func__);
+ mPromise = nullptr;
+ }
}
return NS_OK;
}
@@ -716,10 +726,28 @@ class PrintListenerAdapter final : public nsIWebProgressListener {
return NS_OK;
}
+ void StaticCloneForPrintingCreated(
+ MaybeDiscardedBrowsingContext&& aClonedStaticBrowsingContext) {
+ MOZ_ASSERT(NS_IsMainThread());
+ mClonedStaticBrowsingContext = std::move(aClonedStaticBrowsingContext);
+ mHaveSetBrowsingContext = true;
+ if (mPrintJobFinished && mPromise) {
+ mPromise->Resolve(mClonedStaticBrowsingContext, __func__);
+ mPromise = nullptr;
+ }
+ }
+
+ void NoStaticCloneForPrintingWillBeCreated() {
+ StaticCloneForPrintingCreated(nullptr);
+ }
+
private:
~PrintListenerAdapter() = default;
RefPtr<PrintPromise::Private> mPromise;
+ MaybeDiscardedBrowsingContext mClonedStaticBrowsingContext = nullptr;
+ bool mHaveSetBrowsingContext = false;
+ bool mPrintJobFinished = false;
};
NS_IMPL_ISUPPORTS(PrintListenerAdapter, nsIWebProgressListener)
@@ -735,7 +763,9 @@ already_AddRefed<Promise> CanonicalBrowsingContext::PrintJS(
Print(aPrintSettings)
->Then(
GetCurrentSerialEventTarget(), __func__,
- [promise](bool) { promise->MaybeResolveWithUndefined(); },
+ [promise](MaybeDiscardedBrowsingContext) {
+ promise->MaybeResolveWithUndefined();
+ },
[promise](nsresult aResult) { promise->MaybeReject(aResult); });
return promise.forget();
}
@@ -745,7 +775,72 @@ RefPtr<PrintPromise> CanonicalBrowsingContext::Print(
#ifndef NS_PRINTING
return PrintPromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE, __func__);
#else
+// Content analysis is not supported on non-Windows platforms.
+# if defined(XP_WIN)
+ bool needContentAnalysis = false;
+ nsCOMPtr<nsIContentAnalysis> contentAnalysis =
+ mozilla::components::nsIContentAnalysis::Service();
+ Unused << NS_WARN_IF(!contentAnalysis);
+ if (contentAnalysis) {
+ nsresult rv = contentAnalysis->GetIsActive(&needContentAnalysis);
+ Unused << NS_WARN_IF(NS_FAILED(rv));
+ }
+ if (needContentAnalysis) {
+ auto done = MakeRefPtr<PrintPromise::Private>(__func__);
+ contentanalysis::ContentAnalysis::PrintToPDFToDetermineIfPrintAllowed(
+ this, aPrintSettings)
+ ->Then(
+ GetCurrentSerialEventTarget(), __func__,
+ [done, aPrintSettings = RefPtr{aPrintSettings},
+ self = RefPtr{this}](
+ contentanalysis::ContentAnalysis::PrintAllowedResult aResponse)
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY_LAMBDA mutable {
+ if (aResponse.mAllowed) {
+ self->PrintWithNoContentAnalysis(
+ aPrintSettings, false,
+ aResponse.mCachedStaticDocumentBrowsingContext)
+ ->ChainTo(done.forget(), __func__);
+ } else {
+ // Since we are not doing the second print in this case,
+ // release the clone that is no longer needed.
+ self->ReleaseClonedPrint(
+ aResponse.mCachedStaticDocumentBrowsingContext);
+ done->Reject(NS_ERROR_CONTENT_BLOCKED, __func__);
+ }
+ },
+ [done, self = RefPtr{this}](
+ contentanalysis::ContentAnalysis::PrintAllowedError
+ aErrorResponse) MOZ_CAN_RUN_SCRIPT_BOUNDARY_LAMBDA {
+ // Since we are not doing the second print in this case, release
+ // the clone that is no longer needed.
+ self->ReleaseClonedPrint(
+ aErrorResponse.mCachedStaticDocumentBrowsingContext);
+ done->Reject(aErrorResponse.mError, __func__);
+ });
+ return done;
+ }
+# endif
+ return PrintWithNoContentAnalysis(aPrintSettings, false, nullptr);
+#endif
+}
+void CanonicalBrowsingContext::ReleaseClonedPrint(
+ const MaybeDiscardedBrowsingContext& aClonedStaticBrowsingContext) {
+#ifdef NS_PRINTING
+ auto* browserParent = GetBrowserParent();
+ if (NS_WARN_IF(!browserParent)) {
+ return;
+ }
+ Unused << browserParent->SendDestroyPrintClone(aClonedStaticBrowsingContext);
+#endif
+}
+
+RefPtr<PrintPromise> CanonicalBrowsingContext::PrintWithNoContentAnalysis(
+ nsIPrintSettings* aPrintSettings, bool aForceStaticDocument,
+ const MaybeDiscardedBrowsingContext& aCachedStaticDocument) {
+#ifndef NS_PRINTING
+ return PrintPromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE, __func__);
+#else
auto promise = MakeRefPtr<PrintPromise::Private>(__func__);
auto listener = MakeRefPtr<PrintListenerAdapter>(promise);
if (IsInProcess()) {
@@ -757,12 +852,14 @@ RefPtr<PrintPromise> CanonicalBrowsingContext::Print(
}
ErrorResult rv;
+ listener->NoStaticCloneForPrintingWillBeCreated();
outerWindow->Print(aPrintSettings,
/* aRemotePrintJob = */ nullptr, listener,
/* aDocShellToCloneInto = */ nullptr,
nsGlobalWindowOuter::IsPreview::No,
nsGlobalWindowOuter::IsForWindowDotPrint::No,
- /* aPrintPreviewCallback = */ nullptr, rv);
+ /* aPrintPreviewCallback = */ nullptr,
+ /* aCachedBrowsingContext = */ nullptr, rv);
if (rv.Failed()) {
promise->Reject(rv.StealNSResult(), __func__);
}
@@ -805,12 +902,31 @@ RefPtr<PrintPromise> CanonicalBrowsingContext::Print(
printData.remotePrintJob() =
browserParent->Manager()->SendPRemotePrintJobConstructor(remotePrintJob);
- if (listener) {
- remotePrintJob->RegisterListener(listener);
- }
+ remotePrintJob->RegisterListener(listener);
- if (NS_WARN_IF(!browserParent->SendPrint(this, printData))) {
- promise->Reject(NS_ERROR_FAILURE, __func__);
+ if (!aCachedStaticDocument.IsNullOrDiscarded()) {
+ // There is no cloned static browsing context that
+ // SendPrintClonedPage() will return, so indicate this
+ // so listener can resolve its promise.
+ listener->NoStaticCloneForPrintingWillBeCreated();
+ if (NS_WARN_IF(!browserParent->SendPrintClonedPage(
+ this, printData, aCachedStaticDocument))) {
+ promise->Reject(NS_ERROR_FAILURE, __func__);
+ }
+ } else {
+ RefPtr<PBrowserParent::PrintPromise> printPromise =
+ browserParent->SendPrint(this, printData, aForceStaticDocument);
+ printPromise->Then(
+ GetMainThreadSerialEventTarget(), __func__,
+ [listener](MaybeDiscardedBrowsingContext cachedStaticDocument) {
+ // promise will get resolved by the listener
+ listener->StaticCloneForPrintingCreated(
+ std::move(cachedStaticDocument));
+ },
+ [promise](ResponseRejectReason reason) {
+ NS_WARNING("SendPrint() failed");
+ promise->Reject(NS_ERROR_FAILURE, __func__);
+ });
}
return promise.forget();
#endif
@@ -2245,9 +2361,19 @@ bool CanonicalBrowsingContext::SupportsLoadingInParent(
return false;
}
}
- // If the current document has a beforeunload listener, then we need to
- // start the load in that process after we fire the event.
- if (global->HasBeforeUnload()) {
+
+ // If unloading the current document will cause a beforeunload listener to
+ // run, then we need to start the load in that process after we fire the
+ // event.
+ if (PreOrderWalkFlag([&](BrowsingContext* aBC) {
+ WindowContext* wc = aBC->GetCurrentWindowContext();
+ if (wc && wc->HasBeforeUnload()) {
+ // We can stop as soon as we know at least one beforeunload listener
+ // exists.
+ return WalkFlag::Stop;
+ }
+ return WalkFlag::Next;
+ }) == WalkFlag::Stop) {
return false;
}