Backed out 2 changesets (bug 1653334) for reftest failures at test-print-selection.html. CLOSED TREE

Backed out changeset 6cc6bbaa91f0 (bug 1653334)
Backed out changeset 75a5873f02a4 (bug 1653334)
This commit is contained in:
Butkovits Atila 2020-08-03 15:35:37 +03:00
Родитель 7aee3a7053
Коммит 076d3aa7ed
9 изменённых файлов: 232 добавлений и 116 удалений

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

@ -3432,6 +3432,24 @@ nsDocumentViewer::GetPrintPreviewNumPages(int32_t* aPrintPreviewNumPages) {
return *aPrintPreviewNumPages > 0 ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsDocumentViewer::GetIsIFrameSelected(bool* aIsIFrameSelected) {
*aIsIFrameSelected = false;
NS_ENSURE_TRUE(mPrintJob, NS_ERROR_FAILURE);
*aIsIFrameSelected = mPrintJob->IsIFrameSelected();
return NS_OK;
}
NS_IMETHODIMP
nsDocumentViewer::GetIsRangeSelection(bool* aIsRangeSelection) {
*aIsRangeSelection = false;
NS_ENSURE_TRUE(mPrintJob, NS_ERROR_FAILURE);
*aIsRangeSelection = mPrintJob->IsRangeSelection();
return NS_OK;
}
//----------------------------------------------------------------------------------
// Printing/Print Preview Helpers
//----------------------------------------------------------------------------------

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

@ -59,10 +59,8 @@ class nsPrintData {
nsCOMArray<nsIWebProgressListener> mPrintProgressListeners;
nsCOMPtr<nsIPrintProgressParams> mPrintProgressParams;
// If there is a focused iframe, mSelectionRoot is set to its nsPrintObject.
// Otherwise, if there is a selection, it is set to the root nsPrintObject.
// Otherwise, it is unset.
nsPrintObject* mSelectionRoot = nullptr;
nsCOMPtr<nsPIDOMWindowOuter> mCurrentFocusWin; // cache a pointer to the
// currently focused window
// Array of non-owning pointers to all the nsPrintObjects owned by this
// nsPrintData. This includes this->mPrintObject, as well as all of its

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

@ -270,6 +270,31 @@ static bool IsParentAFrameSet(nsIDocShell* aParent) {
return isFrameSet;
}
static nsPrintObject* FindPrintObjectByDOMWin(nsPrintObject* aPO,
nsPIDOMWindowOuter* aDOMWin) {
NS_ASSERTION(aPO, "Pointer is null!");
// Often the CurFocused DOMWindow is passed in
// andit is valid for it to be null, so short circut
if (!aDOMWin) {
return nullptr;
}
nsCOMPtr<Document> doc = aDOMWin->GetDoc();
if (aPO->mDocument && aPO->mDocument->GetOriginalDocument() == doc) {
return aPO;
}
for (const UniquePtr<nsPrintObject>& kid : aPO->mKids) {
nsPrintObject* po = FindPrintObjectByDOMWin(kid.get(), aDOMWin);
if (po) {
return po;
}
}
return nullptr;
}
static std::tuple<nsPageSequenceFrame*, int32_t>
GetSeqFrameAndCountPagesInternal(const UniquePtr<nsPrintObject>& aPO) {
if (!aPO) {
@ -295,23 +320,18 @@ GetSeqFrameAndCountPagesInternal(const UniquePtr<nsPrintObject>& aPO) {
}
/**
* Build a tree of nsPrintObjects under aPO. It also appends a (depth first)
* flat list of all the nsPrintObjects created to aPrintData->mPrintDocList. If
* one of the nsPrintObject's document is the focused document, then the print
* object is set as aPrintData->mSelectionRoot.
* @param aParentPO The parent nsPrintObject to populate, must not be null.
* @param aFocusedDoc Document from the window that had focus when print was
* initiated.
* @param aPrintData nsPrintData for the current print, must not be null.
* The outparam aDocList returns a (depth first) flat list of all the
* nsPrintObjects created.
*/
static void BuildNestedPrintObjects(const UniquePtr<nsPrintObject>& aParentPO,
const RefPtr<Document>& aFocusedDoc,
RefPtr<nsPrintData>& aPrintData) {
MOZ_ASSERT(aParentPO);
MOZ_ASSERT(aPrintData);
static void BuildNestedPrintObjects(Document* aDocument,
const UniquePtr<nsPrintObject>& aPO,
nsTArray<nsPrintObject*>* aDocList) {
MOZ_ASSERT(aDocument, "Pointer is null!");
MOZ_ASSERT(aDocList, "Pointer is null!");
MOZ_ASSERT(aPO, "Pointer is null!");
nsTArray<Document::PendingFrameStaticClone> pendingClones =
aParentPO->mDocument->TakePendingFrameStaticClones();
aDocument->TakePendingFrameStaticClones();
for (auto& clone : pendingClones) {
if (NS_WARN_IF(!clone.mStaticCloneOf)) {
continue;
@ -330,39 +350,14 @@ static void BuildNestedPrintObjects(const UniquePtr<nsPrintObject>& aParentPO,
continue;
}
nsIDocShell* sourceDocShell =
clone.mStaticCloneOf->GetDocShell(IgnoreErrors());
if (!sourceDocShell) {
continue;
}
Document* sourceDoc = sourceDocShell->GetDocument();
if (!sourceDoc) {
continue;
}
auto childPO = MakeUnique<nsPrintObject>();
rv = childPO->InitAsNestedObject(docshell, doc, sourceDoc, aParentPO.get());
rv = childPO->InitAsNestedObject(docshell, doc, aPO.get());
if (NS_FAILED(rv)) {
MOZ_ASSERT_UNREACHABLE("Init failed?");
}
// If the childPO is for an iframe and its original document is focusedDoc
// then always set as the selection root.
if (childPO->mFrameType == eIFrame &&
doc->GetOriginalDocument() == aFocusedDoc) {
aPrintData->mSelectionRoot = childPO.get();
} else if (!aPrintData->mSelectionRoot && childPO->mHasSelection) {
// If there is no focused iframe but there is a selection in one or more
// frames then we want to set the root nsPrintObject as the focus root so
// that later EnablePrintingSelectionOnly can search for and enable all
// nsPrintObjects containing selections.
aPrintData->mSelectionRoot = aPrintData->mPrintObject.get();
}
aPrintData->mPrintDocList.AppendElement(childPO.get());
BuildNestedPrintObjects(childPO, aFocusedDoc, aPrintData);
aParentPO->mKids.AppendElement(std::move(childPO));
aPO->mKids.AppendElement(std::move(childPO));
aDocList->AppendElement(aPO->mKids.LastElement().get());
BuildNestedPrintObjects(doc, aPO->mKids.LastElement(), aDocList);
}
}
@ -670,8 +665,10 @@ nsresult nsPrintJob::DoCommonPrint(bool aIsPrintPreview,
printData->mPrintProgressListeners.AppendObject(aWebProgressListener);
}
// Get the document from the currently focused window.
RefPtr<Document> focusedDoc = FindFocusedDocument();
// Get the currently focused window and cache it
// because the Print Dialog will "steal" focus and later when you try
// to get the currently focused windows it will be nullptr
printData->mCurrentFocusWin = FindFocusedDOMWindow();
// Get the docshell for this documentviewer
nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell, &rv));
@ -698,7 +695,8 @@ nsresult nsPrintJob::DoCommonPrint(bool aIsPrintPreview,
printData->mPrintObject->mFrameType =
printData->mIsParentAFrameSet ? eFrameSet : eDoc;
BuildNestedPrintObjects(printData->mPrintObject, focusedDoc, printData);
BuildNestedPrintObjects(printData->mPrintObject->mDocument,
printData->mPrintObject, &printData->mPrintDocList);
}
if (!aSourceDoc->IsStaticDocument()) {
@ -756,8 +754,11 @@ nsresult nsPrintJob::DoCommonPrint(bool aIsPrintPreview,
}
// Now determine how to set up the Frame print UI
bool isSelection = IsThereARangeSelection(printData->mCurrentFocusWin);
bool isIFrameSelected = IsThereAnIFrameSelected(
docShell, printData->mCurrentFocusWin, printData->mIsParentAFrameSet);
printData->mPrintSettings->SetPrintOptions(
nsIPrintSettings::kEnableSelectionRB, !!printData->mSelectionRoot);
nsIPrintSettings::kEnableSelectionRB, isSelection || isIFrameSelected);
bool printingViaParent =
XRE_IsContentProcess() && Preferences::GetBool("print.print_via_parent");
@ -996,6 +997,29 @@ nsresult nsPrintJob::PrintPreview(
return CommonPrint(true, aPrintSettings, aWebProgressListener, aSourceDoc);
}
//----------------------------------------------------------------------------------
bool nsPrintJob::IsIFrameSelected() {
// Get the docshell for this documentviewer
nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
// Get the currently focused window
nsCOMPtr<nsPIDOMWindowOuter> currentFocusWin = FindFocusedDOMWindow();
if (currentFocusWin && docShell) {
// Get whether the doc contains a frameset
// Also, check to see if the currently focus docshell
// is a child of this docshell
bool isParentFrameSet;
return IsThereAnIFrameSelected(docShell, currentFocusWin, isParentFrameSet);
}
return false;
}
//----------------------------------------------------------------------------------
bool nsPrintJob::IsRangeSelection() {
// Get the currently focused window
nsCOMPtr<nsPIDOMWindowOuter> currentFocusWin = FindFocusedDOMWindow();
return IsThereARangeSelection(currentFocusWin);
}
//----------------------------------------------------------------------------------
int32_t nsPrintJob::GetPrintPreviewNumPages() {
// When calling this function, the FinishPrintPreview() function might not
@ -1090,6 +1114,68 @@ void nsPrintJob::ShowPrintProgress(bool aIsForPrinting, bool& aDoNotify) {
}
}
//---------------------------------------------------------------------
bool nsPrintJob::IsThereARangeSelection(nsPIDOMWindowOuter* aDOMWin) {
if (mDisallowSelectionPrint || !aDOMWin) {
return false;
}
PresShell* presShell = aDOMWin->GetDocShell()->GetPresShell();
if (!presShell) {
return false;
}
// check here to see if there is a range selection
// so we know whether to turn on the "Selection" radio button
Selection* selection = presShell->GetCurrentSelection(SelectionType::eNormal);
if (!selection) {
return false;
}
int32_t rangeCount = selection->RangeCount();
if (!rangeCount) {
return false;
}
if (rangeCount > 1) {
return true;
}
// check to make sure it isn't an insertion selection
return selection->GetRangeAt(0) && !selection->IsCollapsed();
}
//---------------------------------------------------------------------
bool nsPrintJob::IsThereAnIFrameSelected(nsIDocShell* aDocShell,
nsPIDOMWindowOuter* aDOMWin,
bool& aIsParentFrameSet) {
aIsParentFrameSet = IsParentAFrameSet(aDocShell);
bool iFrameIsSelected = false;
if (mPrt && mPrt->mPrintObject) {
nsPrintObject* po =
FindPrintObjectByDOMWin(mPrt->mPrintObject.get(), aDOMWin);
iFrameIsSelected = po && po->mFrameType == eIFrame;
} else {
// First, check to see if we are a frameset
if (!aIsParentFrameSet) {
// Check to see if there is a currenlt focused frame
// if so, it means the selected frame is either the main docshell
// or an IFRAME
if (aDOMWin) {
// Get the main docshell's DOMWin to see if it matches
// the frame that is selected
nsPIDOMWindowOuter* domWin =
aDocShell ? aDocShell->GetWindow() : nullptr;
if (domWin != aDOMWin) {
iFrameIsSelected = true; // we have a selected IFRAME
}
}
}
}
return iFrameIsSelected;
}
// static
void nsPrintJob::GetDisplayTitleAndURL(Document& aDoc,
nsIPrintSettings* aSettings,
@ -1925,10 +2011,7 @@ nsresult nsPrintJob::ReflowPrintObject(const UniquePtr<nsPrintObject>& aPO) {
int16_t printRangeType = nsIPrintSettings::kRangeAllPages;
printData->mPrintSettings->GetPrintRange(&printRangeType);
if (printRangeType == nsIPrintSettings::kRangeSelection) {
// If we fail to remove the nodes then we should fail to print, because if
// the user was trying to print a small selection from a large document,
// sending the whole document to a real printer would be very frustrating.
MOZ_TRY(DeleteNonSelectedNodes(*aPO->mDocument));
DeleteNonSelectedNodes(*aPO->mDocument);
}
bool doReturn = false;
@ -2101,11 +2184,6 @@ MOZ_CAN_RUN_SCRIPT_BOUNDARY static nsresult DeleteNonSelectedNodes(
MOZ_ASSERT(!selection->RangeCount());
nsINode* bodyNode = aDoc.GetBodyElement();
if (!bodyNode) {
// We don't currently support printing selections that are not in a body.
return NS_ERROR_FAILURE;
}
nsINode* startNode = bodyNode;
uint32_t startOffset = 0;
@ -2444,7 +2522,10 @@ void nsPrintJob::SetIsPrintPreview(bool aIsPrintPreview) {
}
}
Document* nsPrintJob::FindFocusedDocument() const {
/** ---------------------------------------------------
* Get the Focused Frame for a documentviewer
*/
already_AddRefed<nsPIDOMWindowOuter> nsPrintJob::FindFocusedDOMWindow() const {
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
NS_ENSURE_TRUE(fm, nullptr);
@ -2461,7 +2542,7 @@ Document* nsPrintJob::FindFocusedDocument() const {
NS_ENSURE_TRUE(focusedWindow, nullptr);
if (IsWindowsInOurSubTree(focusedWindow)) {
return focusedWindow->GetDoc();
return focusedWindow.forget();
}
return nullptr;
@ -2561,20 +2642,50 @@ nsresult nsPrintJob::EnablePOsForPrinting() {
return NS_OK;
}
// This means we are either printing a selected iframe or
// we are printing the current selection.
MOZ_ASSERT(printRangeType == nsIPrintSettings::kRangeSelection);
NS_ENSURE_STATE(printData->mSelectionRoot);
// This means we are either printed a selected IFrame or
// we are printing the current selection
// If mSelectionRoot is a selected iframe without a selection, then just
// enable normally from that point.
if (printData->mSelectionRoot->mFrameType == eIFrame &&
!printData->mSelectionRoot->mHasSelection) {
printData->mSelectionRoot->EnablePrinting(true);
} else {
// Otherwise, only enable nsPrintObjects that have a selection.
printData->mSelectionRoot->EnablePrintingSelectionOnly();
MOZ_ASSERT(printRangeType == nsIPrintSettings::kRangeSelection);
// If the currentFocusDOMWin can'r be null if something is selected
if (!printData->mCurrentFocusWin) {
for (uint32_t i = 0; i < printData->mPrintDocList.Length(); i++) {
nsPrintObject* po = printData->mPrintDocList.ElementAt(i);
NS_ASSERTION(po, "nsPrintObject can't be null!");
nsCOMPtr<nsPIDOMWindowOuter> domWin = po->mDocShell->GetWindow();
if (IsThereARangeSelection(domWin)) {
printData->mCurrentFocusWin = std::move(domWin);
po->EnablePrinting(true);
break;
}
}
return NS_OK;
}
// Find the selected IFrame
nsPrintObject* po = FindPrintObjectByDOMWin(printData->mPrintObject.get(),
printData->mCurrentFocusWin);
if (!po) {
return NS_OK;
}
// Now, only enable this POs (the selected PO) and all of its children
po->EnablePrinting(true);
// check to see if we have a range selection,
// as oppose to a insert selection
// this means if the user just clicked on the IFrame then
// there will not be a selection so we want the entire page to print
//
// XXX this is sort of a hack right here to make the page
// not try to reposition itself when printing selection
nsPIDOMWindowOuter* domWin =
po->mDocument->GetOriginalDocument()->GetWindow();
if (!IsThereARangeSelection(domWin)) {
printRangeType = nsIPrintSettings::kRangeAllPages;
printData->mPrintSettings->SetPrintRange(printRangeType);
}
PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType]));
return NS_OK;
}

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

@ -119,6 +119,8 @@ class nsPrintJob final : public nsIObserver,
bool IsDoingPrint() const { return mIsDoingPrinting; }
bool IsDoingPrintPreview() const { return mIsDoingPrintPreview; }
bool HasEverPrinted() const { return mHasEverPrinted; }
bool IsIFrameSelected();
bool IsRangeSelection();
/// If the returned value is not greater than zero, an error occurred.
int32_t GetPrintPreviewNumPages();
already_AddRefed<nsIPrintSettings> GetCurrentPrintSettings();
@ -164,6 +166,8 @@ class nsPrintJob final : public nsIObserver,
nsresult& aStatus);
nsresult DoPrint(const mozilla::UniquePtr<nsPrintObject>& aPO);
void SetPrintPO(nsPrintObject* aPO, bool aPrint);
/**
* Filters out certain user events while Print Preview is open to prevent
* the user from interacting with the Print Preview document and breaking
@ -184,14 +188,17 @@ class nsPrintJob final : public nsIObserver,
nsIPrintProgressParams* aParams);
void EllipseLongString(nsAString& aStr, const uint32_t aLen, bool aDoFront);
bool IsThereARangeSelection(nsPIDOMWindowOuter* aDOMWin);
nsresult StartPagePrintTimer(const mozilla::UniquePtr<nsPrintObject>& aPO);
bool IsWindowsInOurSubTree(nsPIDOMWindowOuter* aDOMWindow) const;
bool IsThereAnIFrameSelected(nsIDocShell* aDocShell,
nsPIDOMWindowOuter* aDOMWin,
bool& aIsParentFrameSet);
/**
* @return The document from the focused windows for a document viewer.
*/
Document* FindFocusedDocument() const;
// get the currently infocus frame for the document viewer
already_AddRefed<nsPIDOMWindowOuter> FindFocusedDOMWindow() const;
/// Customizes the behaviour of GetDisplayTitleAndURL.
enum class DocTitleDefault : uint32_t { eDocURLElseFallback, eFallback };
@ -292,6 +299,7 @@ class nsPrintJob final : public nsIObserver,
bool mIsDestroying = false;
bool mDisallowSelectionPrint = false;
bool mIsForModalWindow = false;
bool mHasMozPrintCallback = false;
};
#endif // nsPrintJob_h

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

@ -104,12 +104,8 @@ static nsINode* GetCorrespondingNodeInDocument(const nsINode* aOrigNode,
* nodes, we cannot reuse an array of nsRange objects across multiple static
* clone documents. For that reason we cache a new array of ranges on each
* static clone that we create.
*
* @param aSourceDoc the document from which we are caching selection ranges
* @param aStaticClone the document that will hold the cache
* @return true if a selection range was cached
*/
static bool CachePrintSelectionRanges(const Document& aSourceDoc,
static void CachePrintSelectionRanges(const Document& aSourceDoc,
Document& aStaticClone) {
MOZ_ASSERT(aStaticClone.IsStaticDocument());
MOZ_ASSERT(!aStaticClone.GetProperty(nsGkAtoms::printselectionranges));
@ -126,12 +122,12 @@ static bool CachePrintSelectionRanges(const Document& aSourceDoc,
}
if (!origSelection && !origRanges) {
return false;
return;
}
size_t rangeCount =
sourceDocIsStatic ? origRanges->Length() : origSelection->RangeCount();
auto printRanges = MakeUnique<nsTArray<RefPtr<nsRange>>>(rangeCount);
auto* printRanges = new nsTArray<RefPtr<nsRange>>(rangeCount);
for (size_t i = 0; i < rangeCount; ++i) {
const nsRange* range = sourceDocIsStatic ? origRanges->ElementAt(i).get()
@ -160,14 +156,8 @@ static bool CachePrintSelectionRanges(const Document& aSourceDoc,
}
}
if (printRanges->IsEmpty()) {
return false;
}
aStaticClone.SetProperty(nsGkAtoms::printselectionranges,
printRanges.release(),
aStaticClone.SetProperty(nsGkAtoms::printselectionranges, printRanges,
nsINode::DeleteProperty<nsTArray<RefPtr<nsRange>>>);
return true;
}
nsresult nsPrintObject::InitAsRootObject(nsIDocShell* aDocShell, Document* aDoc,
@ -208,7 +198,7 @@ nsresult nsPrintObject::InitAsRootObject(nsIDocShell* aDocShell, Document* aDoc,
mDocument = aDoc->CreateStaticClone(mDocShell);
NS_ENSURE_STATE(mDocument);
mHasSelection = CachePrintSelectionRanges(*aDoc, *mDocument);
CachePrintSelectionRanges(*aDoc, *mDocument);
nsCOMPtr<nsIContentViewer> viewer;
mDocShell->GetContentViewer(getter_AddRefs(viewer));
@ -220,7 +210,6 @@ nsresult nsPrintObject::InitAsRootObject(nsIDocShell* aDocShell, Document* aDoc,
nsresult nsPrintObject::InitAsNestedObject(nsIDocShell* aDocShell,
Document* aDoc,
Document* aSourceOfDoc,
nsPrintObject* aParent) {
NS_ENSURE_STATE(aDocShell);
NS_ENSURE_STATE(aDoc);
@ -242,12 +231,6 @@ nsresult nsPrintObject::InitAsNestedObject(nsIDocShell* aDocShell,
mFrameType = eIFrame;
}
// We need to use the document that aDoc was cloned from (aSourceOfDoc) and
// not aDoc->GetOriginalDocument(), because if aSourceOfDoc is a static clone
// aDoc->GetOriginalDocument() will be aSourceOfDoc's original document, which
// may now contain a different or no selection.
mHasSelection = CachePrintSelectionRanges(*aSourceOfDoc, *aDoc);
return NS_OK;
}
@ -272,11 +255,3 @@ void nsPrintObject::EnablePrinting(bool aEnable) {
kid->EnablePrinting(aEnable);
}
}
void nsPrintObject::EnablePrintingSelectionOnly() {
mPrintingIsEnabled = mHasSelection;
for (const UniquePtr<nsPrintObject>& kid : mKids) {
kid->EnablePrintingSelectionOnly();
}
}

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

@ -38,7 +38,6 @@ class nsPrintObject {
bool aForPrintPreview);
nsresult InitAsNestedObject(nsIDocShell* aDocShell,
mozilla::dom::Document* aDoc,
mozilla::dom::Document* aSourceOfDoc,
nsPrintObject* aParent);
void DestroyPresentation();
@ -48,12 +47,6 @@ class nsPrintObject {
* from the given item down into the tree
*/
void EnablePrinting(bool aEnable);
/**
* Recursively sets all the PO items to be printed if they have a selection.
*/
void EnablePrintingSelectionOnly();
bool PrintingIsEnabled() const { return mPrintingIsEnabled; }
// Data Members
@ -73,7 +66,6 @@ class nsPrintObject {
bool mHasBeenPrinted;
bool mInvisible; // Indicates PO is set to not visible by CSS
bool mDidCreateDocShell;
bool mHasSelection = false;
float mShrinkRatio;
float mZoomRatio;

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

@ -45,6 +45,16 @@ interface nsIWebBrowserPrint : nsISupports
*/
readonly attribute boolean doingPrintPreview;
/**
* This returns whether there is an IFrame selected
*/
readonly attribute boolean isIFrameSelected;
/**
* This returns whether there is a "range" selection
*/
readonly attribute boolean isRangeSelection;
/**
* This returns the total number of pages for the Print Preview
*/

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

@ -72,6 +72,8 @@ struct PrintData {
nsString deviceName;
double printableWidthInInches;
double printableHeightInInches;
bool isIFrameSelected;
bool isRangeSelection;
uint8_t[] devModeData;
/**

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

@ -166,6 +166,8 @@ nsPrintSettingsService::SerializeToPrintData(nsIPrintSettings* aSettings,
// data->deviceName() default-initializes
data->printableWidthInInches() = 0;
data->printableHeightInInches() = 0;
data->isIFrameSelected() = false;
data->isRangeSelection() = false;
// data->GTKPrintSettings() default-initializes
// data->printJobName() default-initializes
data->printAllPages() = true;