Bug 1413834 - part 1: Limit frame traversal and getting of next tabindex inside scope owned by document root, r=smaug

--HG--
extra : rebase_source : 6a9bca46f5e98311b0179b8b44bebe59bb77e676
This commit is contained in:
ben.tian@gmail.com 2018-01-26 17:47:44 +02:00
parent 6cfd4299c2
commit 8e8a01efb7
4 changed files with 69 additions and 22 deletions

View File

@ -13,8 +13,8 @@
#include "nsGkAtoms.h"
#include "nsGlobalWindow.h"
#include "nsContentUtils.h"
#include "nsDocument.h"
#include "nsIContentParent.h"
#include "nsIDocument.h"
#include "nsPIDOMWindow.h"
#include "nsIDOMChromeWindow.h"
#include "nsIDOMElement.h"
@ -2603,7 +2603,8 @@ nsFocusManager::GetSelectionLocation(nsIDocument* aDocument,
false, // aVisual
false, // aLockInScrollView
true, // aFollowOOFs
false // aSkipPopupChecks
false, // aSkipPopupChecks
false // aSkipShadow
);
NS_ENSURE_SUCCESS(rv, rv);
@ -3119,7 +3120,8 @@ nsFocusManager::GetNextTabbableContent(nsIPresShell* aPresShell,
false, // aVisual
false, // aLockInScrollView
true, // aFollowOOFs
aForDocumentNavigation // aSkipPopupChecks
aForDocumentNavigation, // aSkipPopupChecks
nsDocument::IsShadowDOMEnabled(aRootContent) // aSkipShadow
);
NS_ENSURE_SUCCESS(rv, rv);
@ -3408,9 +3410,16 @@ nsFocusManager::GetNextTabIndex(nsIContent* aParent,
for (nsIContent* child = aParent->GetFirstChild();
child;
child = child->GetNextSibling()) {
childTabIndex = GetNextTabIndex(child, aCurrentTabIndex, aForward);
if (childTabIndex > aCurrentTabIndex && childTabIndex != tabIndex) {
tabIndex = (tabIndex == 0 || childTabIndex < tabIndex) ? childTabIndex : tabIndex;
MOZ_ASSERT(!child->IsHTMLElement(nsGkAtoms::slot),
"Slots shouldn't appear in light DOM");
// Skip child's descendants if child is a shadow host, as they are
// in the focus navigation scope owned by child's shadow root
if (!(nsDocument::IsShadowDOMEnabled(aParent) && child->GetShadowRoot())) {
childTabIndex = GetNextTabIndex(child, aCurrentTabIndex, aForward);
if (childTabIndex > aCurrentTabIndex && childTabIndex != tabIndex) {
tabIndex = (tabIndex == 0 || childTabIndex < tabIndex) ? childTabIndex : tabIndex;
}
}
nsAutoString tabIndexStr;
@ -3429,10 +3438,17 @@ nsFocusManager::GetNextTabIndex(nsIContent* aParent,
for (nsIContent* child = aParent->GetFirstChild();
child;
child = child->GetNextSibling()) {
childTabIndex = GetNextTabIndex(child, aCurrentTabIndex, aForward);
if ((aCurrentTabIndex == 0 && childTabIndex > tabIndex) ||
(childTabIndex < aCurrentTabIndex && childTabIndex > tabIndex)) {
tabIndex = childTabIndex;
MOZ_ASSERT(!child->IsHTMLElement(nsGkAtoms::slot),
"Slots shouldn't appear in light DOM");
// Skip child's descendants if child is a shadow host, as they are
// in the focus navigation scope owned by child's shadow root
if (!(nsDocument::IsShadowDOMEnabled(aParent) && child->GetShadowRoot())) {
childTabIndex = GetNextTabIndex(child, aCurrentTabIndex, aForward);
if ((aCurrentTabIndex == 0 && childTabIndex > tabIndex) ||
(childTabIndex < aCurrentTabIndex && childTabIndex > tabIndex)) {
tabIndex = childTabIndex;
}
}
nsAutoString tabIndexStr;

View File

@ -29,7 +29,7 @@ public:
nsFrameIterator(nsPresContext* aPresContext, nsIFrame *aStart,
nsIteratorType aType, bool aLockScroll, bool aFollowOOFs,
bool aSkipPopupChecks);
bool aSkipPopupChecks, bool aSkipShadow);
protected:
virtual ~nsFrameIterator() {}
@ -94,6 +94,7 @@ protected:
const bool mLockScroll;
const bool mFollowOOFs;
const bool mSkipPopupChecks;
const bool mSkipShadow;
const nsIteratorType mType;
private:
@ -111,8 +112,10 @@ class nsVisualIterator: public nsFrameIterator
public:
nsVisualIterator(nsPresContext* aPresContext, nsIFrame *aStart,
nsIteratorType aType, bool aLockScroll,
bool aFollowOOFs, bool aSkipPopupChecks) :
nsFrameIterator(aPresContext, aStart, aType, aLockScroll, aFollowOOFs, aSkipPopupChecks) {}
bool aFollowOOFs, bool aSkipPopupChecks,
bool aSkipShadow) :
nsFrameIterator(aPresContext, aStart, aType, aLockScroll,
aFollowOOFs, aSkipPopupChecks, aSkipShadow) {}
protected:
nsIFrame* GetFirstChildInner(nsIFrame* aFrame) override;
@ -143,7 +146,8 @@ NS_NewFrameTraversal(nsIFrameEnumerator **aEnumerator,
bool aVisual,
bool aLockInScrollView,
bool aFollowOOFs,
bool aSkipPopupChecks)
bool aSkipPopupChecks,
bool aSkipShadow)
{
if (!aEnumerator || !aStart)
return NS_ERROR_NULL_POINTER;
@ -155,10 +159,12 @@ NS_NewFrameTraversal(nsIFrameEnumerator **aEnumerator,
nsCOMPtr<nsIFrameEnumerator> trav;
if (aVisual) {
trav = new nsVisualIterator(aPresContext, aStart, aType,
aLockInScrollView, aFollowOOFs, aSkipPopupChecks);
aLockInScrollView, aFollowOOFs,
aSkipPopupChecks, aSkipShadow);
} else {
trav = new nsFrameIterator(aPresContext, aStart, aType,
aLockInScrollView, aFollowOOFs, aSkipPopupChecks);
aLockInScrollView, aFollowOOFs,
aSkipPopupChecks, aSkipShadow);
}
trav.forget(aEnumerator);
return NS_OK;
@ -187,7 +193,8 @@ NS_IMETHODIMP
{
return NS_NewFrameTraversal(aEnumerator, aPresContext, aStart,
static_cast<nsIteratorType>(aType),
aVisual, aLockInScrollView, aFollowOOFs, aSkipPopupChecks);
aVisual, aLockInScrollView, aFollowOOFs,
aSkipPopupChecks, false /* aSkipShadow */);
}
// nsFrameIterator implementation
@ -196,11 +203,13 @@ NS_IMPL_ISUPPORTS(nsFrameIterator, nsIFrameEnumerator)
nsFrameIterator::nsFrameIterator(nsPresContext* aPresContext, nsIFrame *aStart,
nsIteratorType aType, bool aLockInScrollView,
bool aFollowOOFs, bool aSkipPopupChecks)
bool aFollowOOFs, bool aSkipPopupChecks,
bool aSkipShadow)
: mPresContext(aPresContext),
mLockScroll(aLockInScrollView),
mFollowOOFs(aFollowOOFs),
mSkipPopupChecks(aSkipPopupChecks),
mSkipShadow(aSkipShadow),
mType(aType),
mStart(aStart),
mCurrent(aStart),
@ -402,6 +411,15 @@ nsFrameIterator::GetParentFrameNotPopup(nsIFrame* aFrame)
nsIFrame*
nsFrameIterator::GetFirstChild(nsIFrame* aFrame)
{
if (mSkipShadow) {
// Skip frames rendered from contents in shadow tree,
// primarily for focus navigation
nsIContent* content = aFrame->GetContent();
if (content && content->GetShadowRoot()) {
return nullptr;
}
}
nsIFrame* result = GetFirstChildInner(aFrame);
if (mLockScroll && result && result->IsScrollFrame())
return nullptr;
@ -417,6 +435,15 @@ nsFrameIterator::GetFirstChild(nsIFrame* aFrame)
nsIFrame*
nsFrameIterator::GetLastChild(nsIFrame* aFrame)
{
if (mSkipShadow) {
// Skip frames rendered from contents in shadow tree,
// primarily for focus navigation
nsIContent* content = aFrame->GetContent();
if (content && content->GetShadowRoot()) {
return nullptr;
}
}
nsIFrame* result = GetLastChildInner(aFrame);
if (mLockScroll && result && result->IsScrollFrame())
return nullptr;

View File

@ -18,7 +18,8 @@ nsresult NS_NewFrameTraversal(nsIFrameEnumerator **aEnumerator,
bool aVisual,
bool aLockInScrollView,
bool aFollowOOFs,
bool aSkipPopupChecks);
bool aSkipPopupChecks,
bool aSkipShadow);
nsresult NS_CreateFrameTraversal(nsIFrameTraversal** aResult);

View File

@ -8148,7 +8148,8 @@ nsFrame::GetNextPrevLineFromeBlockFrame(nsPresContext* aPresContext,
false, // aVisual
aPos->mScrollViewStop,
false, // aFollowOOFs
false // aSkipPopupChecks
false, // aSkipPopupChecks
false // aSkipShadow
);
if (NS_FAILED(result))
return result;
@ -8245,7 +8246,8 @@ nsFrame::GetNextPrevLineFromeBlockFrame(nsPresContext* aPresContext,
false, // aVisual
aPos->mScrollViewStop,
false, // aFollowOOFs
false // aSkipPopupChecks
false, // aSkipPopupChecks
false // aSkipShadow
);
}
while ( !found ){
@ -9036,7 +9038,8 @@ nsIFrame::GetFrameFromDirection(nsDirection aDirection, bool aVisual,
aVisual && presContext->BidiEnabled(),
aScrollViewStop,
true, // aFollowOOFs
false // aSkipPopupChecks
false, // aSkipPopupChecks
false // aSkipShadow
);
if (NS_FAILED(result))
return result;