зеркало из 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(
|
already_AddRefed<Document> Document::CreateStaticClone(
|
||||||
nsIDocShell* aCloneContainer) {
|
nsIDocShell* aCloneContainer, nsIContentViewer* aViewer,
|
||||||
|
bool* aOutHasInProcessPrintCallbacks) {
|
||||||
MOZ_ASSERT(!mCreatingStaticClone);
|
MOZ_ASSERT(!mCreatingStaticClone);
|
||||||
MOZ_ASSERT(!GetProperty(nsGkAtoms::adoptedsheetclones));
|
MOZ_ASSERT(!GetProperty(nsGkAtoms::adoptedsheetclones));
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(aViewer);
|
||||||
|
|
||||||
mCreatingStaticClone = true;
|
mCreatingStaticClone = true;
|
||||||
SetProperty(nsGkAtoms::adoptedsheetclones, new AdoptedStyleSheetCloneCache(),
|
SetProperty(nsGkAtoms::adoptedsheetclones, new AdoptedStyleSheetCloneCache(),
|
||||||
nsINode::DeleteProperty<AdoptedStyleSheetCloneCache>);
|
nsINode::DeleteProperty<AdoptedStyleSheetCloneCache>);
|
||||||
|
@ -12295,50 +12298,75 @@ already_AddRefed<Document> Document::CreateStaticClone(
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<Document> clonedDoc = do_QueryInterface(clonedNode);
|
nsCOMPtr<Document> clonedDoc = do_QueryInterface(clonedNode);
|
||||||
if (clonedDoc) {
|
if (!clonedDoc) {
|
||||||
size_t sheetsCount = SheetCount();
|
return nullptr;
|
||||||
for (size_t i = 0; i < sheetsCount; ++i) {
|
}
|
||||||
RefPtr<StyleSheet> sheet = SheetAt(i);
|
|
||||||
if (sheet) {
|
size_t sheetsCount = SheetCount();
|
||||||
if (sheet->IsApplicable()) {
|
for (size_t i = 0; i < sheetsCount; ++i) {
|
||||||
RefPtr<StyleSheet> clonedSheet =
|
RefPtr<StyleSheet> sheet = SheetAt(i);
|
||||||
sheet->Clone(nullptr, nullptr, clonedDoc, nullptr);
|
if (sheet) {
|
||||||
NS_WARNING_ASSERTION(clonedSheet,
|
if (sheet->IsApplicable()) {
|
||||||
"Cloning a stylesheet didn't work!");
|
RefPtr<StyleSheet> clonedSheet =
|
||||||
if (clonedSheet) {
|
sheet->Clone(nullptr, nullptr, clonedDoc, nullptr);
|
||||||
clonedDoc->AddStyleSheet(clonedSheet);
|
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) {
|
for (int t = 0; t < AdditionalSheetTypeCount; ++t) {
|
||||||
auto& sheets = mAdditionalSheets[additionalSheetType(t)];
|
auto& sheets = mAdditionalSheets[additionalSheetType(t)];
|
||||||
for (StyleSheet* sheet : sheets) {
|
for (StyleSheet* sheet : sheets) {
|
||||||
if (sheet->IsApplicable()) {
|
if (sheet->IsApplicable()) {
|
||||||
RefPtr<StyleSheet> clonedSheet =
|
RefPtr<StyleSheet> clonedSheet =
|
||||||
sheet->Clone(nullptr, nullptr, clonedDoc, nullptr);
|
sheet->Clone(nullptr, nullptr, clonedDoc, nullptr);
|
||||||
NS_WARNING_ASSERTION(clonedSheet,
|
NS_WARNING_ASSERTION(clonedSheet, "Cloning a stylesheet didn't work!");
|
||||||
"Cloning a stylesheet didn't work!");
|
if (clonedSheet) {
|
||||||
if (clonedSheet) {
|
clonedDoc->AddAdditionalStyleSheet(additionalSheetType(t),
|
||||||
clonedDoc->AddAdditionalStyleSheet(additionalSheetType(t),
|
clonedSheet);
|
||||||
clonedSheet);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Font faces created with the JS API will not be reflected in the
|
// Font faces created with the JS API will not be reflected in the
|
||||||
// stylesheets and need to be copied over to the cloned document.
|
// stylesheets and need to be copied over to the cloned document.
|
||||||
if (const FontFaceSet* set = GetFonts()) {
|
if (const FontFaceSet* set = GetFonts()) {
|
||||||
set->CopyNonRuleFacesTo(clonedDoc->Fonts());
|
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 =
|
clone.mElement->SetFrameLoader(frameLoader);
|
||||||
static_cast<dom::ReferrerInfo*>(mReferrerInfo.get())->Clone();
|
|
||||||
clonedDoc->mPreloadReferrerInfo = clonedDoc->mReferrerInfo;
|
nsresult rv = frameLoader->FinishStaticClone(
|
||||||
CachePrintSelectionRanges(*this, *clonedDoc);
|
clone.mStaticCloneOf, aOutHasInProcessPrintCallbacks);
|
||||||
|
Unused << NS_WARN_IF(NS_FAILED(rv));
|
||||||
}
|
}
|
||||||
|
|
||||||
return clonedDoc.forget();
|
return clonedDoc.forget();
|
||||||
|
@ -16776,13 +16804,6 @@ bool Document::HasRecentlyStartedForegroundLoads() {
|
||||||
return false;
|
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,
|
void Document::AddPendingFrameStaticClone(nsFrameLoaderOwner* aElement,
|
||||||
nsFrameLoader* aStaticCloneOf) {
|
nsFrameLoader* aStaticCloneOf) {
|
||||||
PendingFrameStaticClone* clone = mPendingFrameStaticClones.AppendElement();
|
PendingFrameStaticClone* clone = mPendingFrameStaticClones.AppendElement();
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
#include "mozilla/SegmentedVector.h"
|
#include "mozilla/SegmentedVector.h"
|
||||||
#include "mozilla/TimeStamp.h"
|
#include "mozilla/TimeStamp.h"
|
||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/UniquePtr.h"
|
||||||
#include <bitset> // for member
|
#include <bitset> // for member
|
||||||
#include "js/friend/DOMProxy.h" // JS::ExpandoAndGeneration
|
#include "js/friend/DOMProxy.h" // JS::ExpandoAndGeneration
|
||||||
|
|
||||||
// XXX We need to include this here to ensure that DefaultDeleter for Servo
|
// 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).
|
* and replace the cloned resources).
|
||||||
*
|
*
|
||||||
* @param aCloneContainer The container for the clone document.
|
* @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
|
* If this document is a static clone, this returns the original
|
||||||
|
@ -3934,7 +3940,6 @@ class Document : public nsINode,
|
||||||
RefPtr<nsFrameLoaderOwner> mElement;
|
RefPtr<nsFrameLoaderOwner> mElement;
|
||||||
RefPtr<nsFrameLoader> mStaticCloneOf;
|
RefPtr<nsFrameLoader> mStaticCloneOf;
|
||||||
};
|
};
|
||||||
nsTArray<PendingFrameStaticClone> TakePendingFrameStaticClones();
|
|
||||||
void AddPendingFrameStaticClone(nsFrameLoaderOwner* aElement,
|
void AddPendingFrameStaticClone(nsFrameLoaderOwner* aElement,
|
||||||
nsFrameLoader* aStaticCloneOf);
|
nsFrameLoader* aStaticCloneOf);
|
||||||
|
|
||||||
|
|
|
@ -2754,9 +2754,8 @@ void nsFrameLoader::ActivateFrameEvent(const nsAString& aType, bool aCapture,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult nsFrameLoader::FinishStaticClone(nsFrameLoader* aStaticCloneOf,
|
nsresult nsFrameLoader::FinishStaticClone(
|
||||||
nsIDocShell** aCloneDocShell,
|
nsFrameLoader* aStaticCloneOf, bool* aOutHasInProcessPrintCallbacks) {
|
||||||
Document** aCloneDocument) {
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(
|
MOZ_DIAGNOSTIC_ASSERT(
|
||||||
!nsContentUtils::IsSafeToRunScript(),
|
!nsContentUtils::IsSafeToRunScript(),
|
||||||
"A script blocker should be on the stack while FinishStaticClone is run");
|
"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())) {
|
if (NS_WARN_IF(IsDead())) {
|
||||||
return NS_ERROR_UNEXPECTED;
|
return NS_ERROR_UNEXPECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NS_WARN_IF(aStaticCloneOf->IsRemoteFrame())) {
|
if (NS_WARN_IF(aStaticCloneOf->IsRemoteFrame())) {
|
||||||
return NS_ERROR_NOT_IMPLEMENTED;
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
@ -2793,12 +2793,9 @@ nsresult nsFrameLoader::FinishStaticClone(nsFrameLoader* aStaticCloneOf,
|
||||||
nsCOMPtr<Document> doc = origDocShell->GetDocument();
|
nsCOMPtr<Document> doc = origDocShell->GetDocument();
|
||||||
NS_ENSURE_STATE(doc);
|
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;
|
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
|
// After the parent document has been fully cloned, a new frameloader will be
|
||||||
// created for the cloned iframe, and `FinishStaticClone` will be called on
|
// created for the cloned iframe, and `FinishStaticClone` will be called on
|
||||||
// it, which will clone the inner document of the source nsFrameLoader.
|
// 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,
|
nsresult FinishStaticClone(nsFrameLoader* aStaticCloneOf,
|
||||||
nsIDocShell** aCloneDocShell,
|
bool* aOutHasInProcessPrintCallbacks);
|
||||||
Document** aCloneDocument);
|
|
||||||
|
|
||||||
// WebIDL methods
|
// WebIDL methods
|
||||||
|
|
||||||
|
|
|
@ -5284,36 +5284,6 @@ void nsGlobalWindowOuter::PrintOuter(ErrorResult& aError) {
|
||||||
#endif
|
#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(
|
Nullable<WindowProxyHolder> nsGlobalWindowOuter::Print(
|
||||||
nsIPrintSettings* aPrintSettings, nsIWebProgressListener* aListener,
|
nsIPrintSettings* aPrintSettings, nsIWebProgressListener* aListener,
|
||||||
nsIDocShell* aDocShellToCloneInto, IsPreview aIsPreview,
|
nsIDocShell* aDocShellToCloneInto, IsPreview aIsPreview,
|
||||||
|
@ -5431,23 +5401,12 @@ Nullable<WindowProxyHolder> nsGlobalWindowOuter::Print(
|
||||||
auto dispatchAfterPrint = MakeScopeExit(
|
auto dispatchAfterPrint = MakeScopeExit(
|
||||||
[&] { DispatchPrintEventToWindowTree(*docToPrint, u"afterprint"_ns); });
|
[&] { DispatchPrintEventToWindowTree(*docToPrint, u"afterprint"_ns); });
|
||||||
|
|
||||||
RefPtr<Document> clone;
|
nsAutoScriptBlocker blockScripts;
|
||||||
{
|
RefPtr<Document> clone =
|
||||||
nsAutoScriptBlocker blockScripts;
|
docToPrint->CreateStaticClone(cloneDocShell, cv, &hasPrintCallbacks);
|
||||||
clone = docToPrint->CreateStaticClone(cloneDocShell);
|
if (!clone) {
|
||||||
if (!clone) {
|
aError.ThrowNotSupportedError("Clone operation for printing failed");
|
||||||
aError.ThrowNotSupportedError("Clone operation for printing failed");
|
return nullptr;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче