зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1557645 - Unify in-process document cloning a bit more. r=jwatt
By passing the content viewer to CreateStaticClone we can do this fairly easily. I'm going to add another entry-point to the clone process and it'd be good if we avoid repeating the SetDocument dance and so on. Differential Revision: https://phabricator.services.mozilla.com/D90315
This commit is contained in:
Родитель
b769c92faf
Коммит
3464071d3d
|
@ -12270,9 +12270,12 @@ static void CachePrintSelectionRanges(const Document& aSourceDoc,
|
|||
}
|
||||
|
||||
already_AddRefed<Document> Document::CreateStaticClone(
|
||||
nsIDocShell* aCloneContainer) {
|
||||
nsIDocShell* aCloneContainer, nsIContentViewer* aViewer,
|
||||
bool* aOutHasInProcessPrintCallbacks) {
|
||||
MOZ_ASSERT(!mCreatingStaticClone);
|
||||
MOZ_ASSERT(!GetProperty(nsGkAtoms::adoptedsheetclones));
|
||||
MOZ_DIAGNOSTIC_ASSERT(aViewer);
|
||||
|
||||
mCreatingStaticClone = true;
|
||||
SetProperty(nsGkAtoms::adoptedsheetclones, new AdoptedStyleSheetCloneCache(),
|
||||
nsINode::DeleteProperty<AdoptedStyleSheetCloneCache>);
|
||||
|
@ -12295,50 +12298,75 @@ already_AddRefed<Document> Document::CreateStaticClone(
|
|||
}
|
||||
|
||||
nsCOMPtr<Document> clonedDoc = do_QueryInterface(clonedNode);
|
||||
if (clonedDoc) {
|
||||
size_t sheetsCount = SheetCount();
|
||||
for (size_t i = 0; i < sheetsCount; ++i) {
|
||||
RefPtr<StyleSheet> sheet = SheetAt(i);
|
||||
if (sheet) {
|
||||
if (sheet->IsApplicable()) {
|
||||
RefPtr<StyleSheet> clonedSheet =
|
||||
sheet->Clone(nullptr, nullptr, clonedDoc, nullptr);
|
||||
NS_WARNING_ASSERTION(clonedSheet,
|
||||
"Cloning a stylesheet didn't work!");
|
||||
if (clonedSheet) {
|
||||
clonedDoc->AddStyleSheet(clonedSheet);
|
||||
}
|
||||
if (!clonedDoc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t sheetsCount = SheetCount();
|
||||
for (size_t i = 0; i < sheetsCount; ++i) {
|
||||
RefPtr<StyleSheet> sheet = SheetAt(i);
|
||||
if (sheet) {
|
||||
if (sheet->IsApplicable()) {
|
||||
RefPtr<StyleSheet> clonedSheet =
|
||||
sheet->Clone(nullptr, nullptr, clonedDoc, nullptr);
|
||||
NS_WARNING_ASSERTION(clonedSheet, "Cloning a stylesheet didn't work!");
|
||||
if (clonedSheet) {
|
||||
clonedDoc->AddStyleSheet(clonedSheet);
|
||||
}
|
||||
}
|
||||
}
|
||||
clonedDoc->CloneAdoptedSheetsFrom(*this);
|
||||
}
|
||||
clonedDoc->CloneAdoptedSheetsFrom(*this);
|
||||
|
||||
for (int t = 0; t < AdditionalSheetTypeCount; ++t) {
|
||||
auto& sheets = mAdditionalSheets[additionalSheetType(t)];
|
||||
for (StyleSheet* sheet : sheets) {
|
||||
if (sheet->IsApplicable()) {
|
||||
RefPtr<StyleSheet> clonedSheet =
|
||||
sheet->Clone(nullptr, nullptr, clonedDoc, nullptr);
|
||||
NS_WARNING_ASSERTION(clonedSheet,
|
||||
"Cloning a stylesheet didn't work!");
|
||||
if (clonedSheet) {
|
||||
clonedDoc->AddAdditionalStyleSheet(additionalSheetType(t),
|
||||
clonedSheet);
|
||||
}
|
||||
for (int t = 0; t < AdditionalSheetTypeCount; ++t) {
|
||||
auto& sheets = mAdditionalSheets[additionalSheetType(t)];
|
||||
for (StyleSheet* sheet : sheets) {
|
||||
if (sheet->IsApplicable()) {
|
||||
RefPtr<StyleSheet> clonedSheet =
|
||||
sheet->Clone(nullptr, nullptr, clonedDoc, nullptr);
|
||||
NS_WARNING_ASSERTION(clonedSheet, "Cloning a stylesheet didn't work!");
|
||||
if (clonedSheet) {
|
||||
clonedDoc->AddAdditionalStyleSheet(additionalSheetType(t),
|
||||
clonedSheet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Font faces created with the JS API will not be reflected in the
|
||||
// stylesheets and need to be copied over to the cloned document.
|
||||
if (const FontFaceSet* set = GetFonts()) {
|
||||
set->CopyNonRuleFacesTo(clonedDoc->Fonts());
|
||||
// Font faces created with the JS API will not be reflected in the
|
||||
// stylesheets and need to be copied over to the cloned document.
|
||||
if (const FontFaceSet* set = GetFonts()) {
|
||||
set->CopyNonRuleFacesTo(clonedDoc->Fonts());
|
||||
}
|
||||
|
||||
clonedDoc->mReferrerInfo =
|
||||
static_cast<dom::ReferrerInfo*>(mReferrerInfo.get())->Clone();
|
||||
clonedDoc->mPreloadReferrerInfo = clonedDoc->mReferrerInfo;
|
||||
CachePrintSelectionRanges(*this, *clonedDoc);
|
||||
|
||||
// We're done with the clone, embed ourselves into the document viewer and
|
||||
// clone our children. The order here is pretty important, because our
|
||||
// document our document needs to have an owner global before we can create
|
||||
// the frame loaders for subdocuments.
|
||||
aViewer->SetDocument(clonedDoc);
|
||||
|
||||
*aOutHasInProcessPrintCallbacks |= clonedDoc->HasPrintCallbacks();
|
||||
|
||||
auto pendingClones = std::move(clonedDoc->mPendingFrameStaticClones);
|
||||
for (const auto& clone : pendingClones) {
|
||||
RefPtr<Element> element = do_QueryObject(clone.mElement);
|
||||
RefPtr<nsFrameLoader> frameLoader =
|
||||
nsFrameLoader::Create(element, /* aNetworkCreated */ false);
|
||||
|
||||
if (NS_WARN_IF(!frameLoader)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
clonedDoc->mReferrerInfo =
|
||||
static_cast<dom::ReferrerInfo*>(mReferrerInfo.get())->Clone();
|
||||
clonedDoc->mPreloadReferrerInfo = clonedDoc->mReferrerInfo;
|
||||
CachePrintSelectionRanges(*this, *clonedDoc);
|
||||
clone.mElement->SetFrameLoader(frameLoader);
|
||||
|
||||
nsresult rv = frameLoader->FinishStaticClone(
|
||||
clone.mStaticCloneOf, aOutHasInProcessPrintCallbacks);
|
||||
Unused << NS_WARN_IF(NS_FAILED(rv));
|
||||
}
|
||||
|
||||
return clonedDoc.forget();
|
||||
|
@ -16776,13 +16804,6 @@ bool Document::HasRecentlyStartedForegroundLoads() {
|
|||
return false;
|
||||
}
|
||||
|
||||
nsTArray<Document::PendingFrameStaticClone>
|
||||
Document::TakePendingFrameStaticClones() {
|
||||
MOZ_ASSERT(mIsStaticDocument,
|
||||
"Cannot have pending frame static clones in non-static documents");
|
||||
return std::move(mPendingFrameStaticClones);
|
||||
}
|
||||
|
||||
void Document::AddPendingFrameStaticClone(nsFrameLoaderOwner* aElement,
|
||||
nsFrameLoader* aStaticCloneOf) {
|
||||
PendingFrameStaticClone* clone = mPendingFrameStaticClones.AppendElement();
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
#include "mozilla/SegmentedVector.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include <bitset> // for member
|
||||
#include <bitset> // for member
|
||||
#include "js/friend/DOMProxy.h" // JS::ExpandoAndGeneration
|
||||
|
||||
// XXX We need to include this here to ensure that DefaultDeleter for Servo
|
||||
|
@ -2830,8 +2830,14 @@ class Document : public nsINode,
|
|||
* and replace the cloned resources).
|
||||
*
|
||||
* @param aCloneContainer The container for the clone document.
|
||||
* @param aContentViewer The viewer for the clone document. Must be the viewer
|
||||
* of aCloneContainer, but callers must have a reference
|
||||
* to it already and ensure it's not null.
|
||||
* @param aOutHasInProcessPrintCallbacks Self-descriptive.
|
||||
*/
|
||||
already_AddRefed<Document> CreateStaticClone(nsIDocShell* aCloneContainer);
|
||||
already_AddRefed<Document> CreateStaticClone(
|
||||
nsIDocShell* aCloneContainer, nsIContentViewer* aContentViewer,
|
||||
bool* aOutHasInProcessPrintCallbacks);
|
||||
|
||||
/**
|
||||
* If this document is a static clone, this returns the original
|
||||
|
@ -3934,7 +3940,6 @@ class Document : public nsINode,
|
|||
RefPtr<nsFrameLoaderOwner> mElement;
|
||||
RefPtr<nsFrameLoader> mStaticCloneOf;
|
||||
};
|
||||
nsTArray<PendingFrameStaticClone> TakePendingFrameStaticClones();
|
||||
void AddPendingFrameStaticClone(nsFrameLoaderOwner* aElement,
|
||||
nsFrameLoader* aStaticCloneOf);
|
||||
|
||||
|
|
|
@ -2754,9 +2754,8 @@ void nsFrameLoader::ActivateFrameEvent(const nsAString& aType, bool aCapture,
|
|||
}
|
||||
}
|
||||
|
||||
nsresult nsFrameLoader::FinishStaticClone(nsFrameLoader* aStaticCloneOf,
|
||||
nsIDocShell** aCloneDocShell,
|
||||
Document** aCloneDocument) {
|
||||
nsresult nsFrameLoader::FinishStaticClone(
|
||||
nsFrameLoader* aStaticCloneOf, bool* aOutHasInProcessPrintCallbacks) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(
|
||||
!nsContentUtils::IsSafeToRunScript(),
|
||||
"A script blocker should be on the stack while FinishStaticClone is run");
|
||||
|
@ -2772,6 +2771,7 @@ nsresult nsFrameLoader::FinishStaticClone(nsFrameLoader* aStaticCloneOf,
|
|||
if (NS_WARN_IF(IsDead())) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(aStaticCloneOf->IsRemoteFrame())) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
@ -2793,12 +2793,9 @@ nsresult nsFrameLoader::FinishStaticClone(nsFrameLoader* aStaticCloneOf,
|
|||
nsCOMPtr<Document> doc = origDocShell->GetDocument();
|
||||
NS_ENSURE_STATE(doc);
|
||||
|
||||
nsCOMPtr<Document> clonedDoc = doc->CreateStaticClone(docShell);
|
||||
nsCOMPtr<Document> clonedDoc =
|
||||
doc->CreateStaticClone(docShell, viewer, aOutHasInProcessPrintCallbacks);
|
||||
|
||||
viewer->SetDocument(clonedDoc);
|
||||
|
||||
docShell.forget(aCloneDocShell);
|
||||
clonedDoc.forget(aCloneDocument);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -146,12 +146,8 @@ class nsFrameLoader final : public nsStubMutationObserver,
|
|||
// After the parent document has been fully cloned, a new frameloader will be
|
||||
// created for the cloned iframe, and `FinishStaticClone` will be called on
|
||||
// it, which will clone the inner document of the source nsFrameLoader.
|
||||
//
|
||||
// The `aCloneDocShell` and `aCloneDocument` outparameters will be filled with
|
||||
// the values from the newly cloned subframe.
|
||||
nsresult FinishStaticClone(nsFrameLoader* aStaticCloneOf,
|
||||
nsIDocShell** aCloneDocShell,
|
||||
Document** aCloneDocument);
|
||||
bool* aOutHasInProcessPrintCallbacks);
|
||||
|
||||
// WebIDL methods
|
||||
|
||||
|
|
|
@ -5284,36 +5284,6 @@ void nsGlobalWindowOuter::PrintOuter(ErrorResult& aError) {
|
|||
#endif
|
||||
}
|
||||
|
||||
// Returns whether there's any print callback.
|
||||
static bool BuildNestedClones(Document& aJustClonedDoc) {
|
||||
bool hasPrintCallbacks = aJustClonedDoc.HasPrintCallbacks();
|
||||
auto pendingFrameClones = aJustClonedDoc.TakePendingFrameStaticClones();
|
||||
for (const auto& clone : pendingFrameClones) {
|
||||
RefPtr<Element> element = do_QueryObject(clone.mElement);
|
||||
RefPtr<nsFrameLoader> frameLoader =
|
||||
nsFrameLoader::Create(element, /* aNetworkCreated */ false);
|
||||
|
||||
if (NS_WARN_IF(!frameLoader)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
clone.mElement->SetFrameLoader(frameLoader);
|
||||
|
||||
nsCOMPtr<nsIDocShell> docshell;
|
||||
RefPtr<Document> doc;
|
||||
nsresult rv = frameLoader->FinishStaticClone(
|
||||
clone.mStaticCloneOf, getter_AddRefs(docshell), getter_AddRefs(doc));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (doc) {
|
||||
hasPrintCallbacks |= BuildNestedClones(*doc);
|
||||
}
|
||||
}
|
||||
return hasPrintCallbacks;
|
||||
}
|
||||
|
||||
Nullable<WindowProxyHolder> nsGlobalWindowOuter::Print(
|
||||
nsIPrintSettings* aPrintSettings, nsIWebProgressListener* aListener,
|
||||
nsIDocShell* aDocShellToCloneInto, IsPreview aIsPreview,
|
||||
|
@ -5431,23 +5401,12 @@ Nullable<WindowProxyHolder> nsGlobalWindowOuter::Print(
|
|||
auto dispatchAfterPrint = MakeScopeExit(
|
||||
[&] { DispatchPrintEventToWindowTree(*docToPrint, u"afterprint"_ns); });
|
||||
|
||||
RefPtr<Document> clone;
|
||||
{
|
||||
nsAutoScriptBlocker blockScripts;
|
||||
clone = docToPrint->CreateStaticClone(cloneDocShell);
|
||||
if (!clone) {
|
||||
aError.ThrowNotSupportedError("Clone operation for printing failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Do this now so that we get a script handling object, and thus can
|
||||
// create our clones.
|
||||
aError = cv->SetDocument(clone);
|
||||
if (aError.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
hasPrintCallbacks |= BuildNestedClones(*clone);
|
||||
nsAutoScriptBlocker blockScripts;
|
||||
RefPtr<Document> clone =
|
||||
docToPrint->CreateStaticClone(cloneDocShell, cv, &hasPrintCallbacks);
|
||||
if (!clone) {
|
||||
aError.ThrowNotSupportedError("Clone operation for printing failed");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче