зеркало из https://github.com/mozilla/pjs.git
bug 108791 - infinite recursion crash when tabbing if there is no focusable content. r=saari, sr=sfraser.
This commit is contained in:
Родитель
6f66239aa4
Коммит
1ebc6d2820
|
@ -2553,11 +2553,24 @@ PrintDocTree(nsIDocShellTreeNode * aParentNode, int aLevel)
|
||||||
#endif // end debug helpers
|
#endif // end debug helpers
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsEventStateManager::ShiftFocus(PRBool forward, nsIContent* aStart)
|
nsEventStateManager::ShiftFocus(PRBool aForward, nsIContent* aStart)
|
||||||
|
{
|
||||||
|
// We use mTabbedThroughDocument to indicate that we have passed
|
||||||
|
// the end (or beginning) of the document we started tabbing from,
|
||||||
|
// without finding anything else to focus. If we pass the end of
|
||||||
|
// the same document again (and the flag is set), we know that there
|
||||||
|
// is no focusable content anywhere in the tree, and should stop.
|
||||||
|
|
||||||
|
mTabbedThroughDocument = PR_FALSE;
|
||||||
|
return ShiftFocusInternal(aForward, aStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsEventStateManager::ShiftFocusInternal(PRBool aForward, nsIContent* aStart)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_DOCSHELL_FOCUS
|
#ifdef DEBUG_DOCSHELL_FOCUS
|
||||||
printf("[%p] ShiftFocus: forward=%d, aStart=%p, mCurrentFocus=%p\n",
|
printf("[%p] ShiftFocus: aForward=%d, aStart=%p, mCurrentFocus=%p\n",
|
||||||
this, forward, aStart, mCurrentFocus);
|
this, aForward, aStart, mCurrentFocus);
|
||||||
#endif
|
#endif
|
||||||
NS_ASSERTION(mPresContext, "no pres context");
|
NS_ASSERTION(mPresContext, "no pres context");
|
||||||
EnsureDocument(mPresContext);
|
EnsureDocument(mPresContext);
|
||||||
|
@ -2600,7 +2613,7 @@ nsEventStateManager::ShiftFocus(PRBool forward, nsIContent* aStart)
|
||||||
// So, use the docshell focus state to disambiguate.
|
// So, use the docshell focus state to disambiguate.
|
||||||
|
|
||||||
docShell->GetHasFocus(&docHasFocus);
|
docShell->GetHasFocus(&docHasFocus);
|
||||||
if (forward) {
|
if (aForward) {
|
||||||
mCurrentFocus = rootContent;
|
mCurrentFocus = rootContent;
|
||||||
NS_IF_ADDREF(mCurrentFocus);
|
NS_IF_ADDREF(mCurrentFocus);
|
||||||
mCurrentTabIndex = 1;
|
mCurrentTabIndex = 1;
|
||||||
|
@ -2627,8 +2640,8 @@ nsEventStateManager::ShiftFocus(PRBool forward, nsIContent* aStart)
|
||||||
presShell->GetPrimaryFrameFor(mCurrentFocus, &curFocusFrame);
|
presShell->GetPrimaryFrameFor(mCurrentFocus, &curFocusFrame);
|
||||||
|
|
||||||
nsCOMPtr<nsIContent> nextFocus;
|
nsCOMPtr<nsIContent> nextFocus;
|
||||||
if (forward || !docHasFocus)
|
if (aForward || !docHasFocus)
|
||||||
GetNextTabbableContent(rootContent, curFocusFrame, forward,
|
GetNextTabbableContent(rootContent, curFocusFrame, aForward,
|
||||||
getter_AddRefs(nextFocus));
|
getter_AddRefs(nextFocus));
|
||||||
|
|
||||||
if (nextFocus) {
|
if (nextFocus) {
|
||||||
|
@ -2648,7 +2661,7 @@ nsEventStateManager::ShiftFocus(PRBool forward, nsIContent* aStart)
|
||||||
presShell->GetPrimaryFrameFor(nextFocus, &nextFocusFrame);
|
presShell->GetPrimaryFrameFor(nextFocus, &nextFocusFrame);
|
||||||
presShell->ScrollFrameIntoView(nextFocusFrame, NS_PRESSHELL_SCROLL_ANYWHERE,
|
presShell->ScrollFrameIntoView(nextFocusFrame, NS_PRESSHELL_SCROLL_ANYWHERE,
|
||||||
NS_PRESSHELL_SCROLL_ANYWHERE);
|
NS_PRESSHELL_SCROLL_ANYWHERE);
|
||||||
TabIntoDocument(subShell, forward);
|
TabIntoDocument(subShell, aForward);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// there is no subshell, so just focus nextFocus
|
// there is no subshell, so just focus nextFocus
|
||||||
|
@ -2683,7 +2696,7 @@ nsEventStateManager::ShiftFocus(PRBool forward, nsIContent* aStart)
|
||||||
focusDocument = !(IsFrameSetDoc(docShell));
|
focusDocument = !(IsFrameSetDoc(docShell));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!forward && !docHasFocus && focusDocument) {
|
if (!aForward && !docHasFocus && focusDocument) {
|
||||||
#ifdef DEBUG_DOCSHELL_FOCUS
|
#ifdef DEBUG_DOCSHELL_FOCUS
|
||||||
printf("Focusing document\n");
|
printf("Focusing document\n");
|
||||||
#endif
|
#endif
|
||||||
|
@ -2696,6 +2709,11 @@ nsEventStateManager::ShiftFocus(PRBool forward, nsIContent* aStart)
|
||||||
// in the same direction starting at the content element
|
// in the same direction starting at the content element
|
||||||
// corresponding to our docshell.
|
// corresponding to our docshell.
|
||||||
|
|
||||||
|
// Guard against infinite recursion (see explanation in ShiftFocus)
|
||||||
|
if (mTabbedThroughDocument)
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
mTabbedThroughDocument = PR_TRUE;
|
||||||
nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(pcContainer);
|
nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(pcContainer);
|
||||||
nsCOMPtr<nsIDocShellTreeItem> treeParent;
|
nsCOMPtr<nsIDocShellTreeItem> treeParent;
|
||||||
treeItem->GetParent(getter_AddRefs(treeParent));
|
treeItem->GetParent(getter_AddRefs(treeParent));
|
||||||
|
@ -2720,13 +2738,13 @@ nsEventStateManager::ShiftFocus(PRBool forward, nsIContent* aStart)
|
||||||
printf("popping out focus to parent docshell\n");
|
printf("popping out focus to parent docshell\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
parentESM->ShiftFocus(forward, shellContent);
|
parentESM->ShiftFocus(aForward, shellContent);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PRBool tookFocus = PR_FALSE;
|
PRBool tookFocus = PR_FALSE;
|
||||||
nsCOMPtr<nsIDocShell> subShell = do_QueryInterface(pcContainer);
|
nsCOMPtr<nsIDocShell> subShell = do_QueryInterface(pcContainer);
|
||||||
if (subShell)
|
if (subShell)
|
||||||
subShell->TabToTreeOwner(forward, &tookFocus);
|
subShell->TabToTreeOwner(aForward, &tookFocus);
|
||||||
|
|
||||||
#ifdef DEBUG_DOCSHEL_FOCUS
|
#ifdef DEBUG_DOCSHEL_FOCUS
|
||||||
printf("offered focus to tree owner, tookFocus=%d\n",
|
printf("offered focus to tree owner, tookFocus=%d\n",
|
||||||
|
@ -2746,7 +2764,7 @@ nsEventStateManager::ShiftFocus(PRBool forward, nsIContent* aStart)
|
||||||
|
|
||||||
NS_IF_RELEASE(mCurrentFocus);
|
NS_IF_RELEASE(mCurrentFocus);
|
||||||
docShell->SetHasFocus(PR_FALSE);
|
docShell->SetHasFocus(PR_FALSE);
|
||||||
ShiftFocus(forward);
|
ShiftFocusInternal(aForward);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,7 +130,7 @@ public:
|
||||||
//Method for centralized distribution of new DOM events
|
//Method for centralized distribution of new DOM events
|
||||||
NS_IMETHOD DispatchNewEvent(nsISupports* aTarget, nsIDOMEvent* aEvent, PRBool *aPreventDefault);
|
NS_IMETHOD DispatchNewEvent(nsISupports* aTarget, nsIDOMEvent* aEvent, PRBool *aPreventDefault);
|
||||||
|
|
||||||
NS_IMETHOD ShiftFocus(PRBool forward, nsIContent* aStart=nsnull);
|
NS_IMETHOD ShiftFocus(PRBool aForward, nsIContent* aStart=nsnull);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void UpdateCursor(nsIPresContext* aPresContext, nsEvent* aEvent, nsIFrame* aTargetFrame, nsEventStatus* aStatus);
|
void UpdateCursor(nsIPresContext* aPresContext, nsEvent* aEvent, nsIFrame* aTargetFrame, nsEventStatus* aStatus);
|
||||||
|
@ -152,6 +152,7 @@ protected:
|
||||||
// DocShell Focus Traversal Methods
|
// DocShell Focus Traversal Methods
|
||||||
//---------------------------------------------
|
//---------------------------------------------
|
||||||
|
|
||||||
|
nsresult ShiftFocusInternal(PRBool aForward, nsIContent* aStart = nsnull);
|
||||||
void TabIntoDocument(nsIDocShell* aDocShell, PRBool aForward);
|
void TabIntoDocument(nsIDocShell* aDocShell, PRBool aForward);
|
||||||
void ShiftFocusByDoc(PRBool forward);
|
void ShiftFocusByDoc(PRBool forward);
|
||||||
PRBool IsFrameSetDoc(nsIDocShell* aDocShell);
|
PRBool IsFrameSetDoc(nsIDocShell* aDocShell);
|
||||||
|
@ -254,6 +255,9 @@ protected:
|
||||||
// So we don't have to keep checking accessibility.browsewithcaret pref
|
// So we don't have to keep checking accessibility.browsewithcaret pref
|
||||||
PRBool mBrowseWithCaret;
|
PRBool mBrowseWithCaret;
|
||||||
|
|
||||||
|
// Recursion guard for tabbing
|
||||||
|
PRBool mTabbedThroughDocument;
|
||||||
|
|
||||||
#ifdef CLICK_HOLD_CONTEXT_MENUS
|
#ifdef CLICK_HOLD_CONTEXT_MENUS
|
||||||
enum { kClickHoldDelay = 500 } ; // 500ms == 1/2 second
|
enum { kClickHoldDelay = 500 } ; // 500ms == 1/2 second
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче