Bug 372665 ��� Crash [@ PresShell::ScrollFrameIntoView] when focusing br during pageload. (Adding ScrollContentIntoView), r+sr=roc

This commit is contained in:
Olli.Pettay%helsinki.fi 2007-03-06 09:53:56 +00:00
Родитель 1fc605fca5
Коммит 4e0ebc823d
9 изменённых файлов: 59 добавлений и 81 удалений

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

@ -2120,18 +2120,16 @@ nsGenericElement::SetFocus(nsPresContext* aPresContext)
// Traditionally focusable elements can take focus as long as they don't set
// the disabled attribute
nsIPresShell *presShell = aPresContext->PresShell();
nsCOMPtr<nsIPresShell> presShell = aPresContext->PresShell();
if (!presShell) {
return;
}
nsIFrame* frame = presShell->GetPrimaryFrameFor(this);
if (frame && frame->IsFocusable() &&
aPresContext->EventStateManager()->SetContentState(this,
NS_EVENT_STATE_FOCUS)) {
// Reget frame, setting content state can change style which can
// cause a frame reconstruction, for example if CSS overflow changes
frame = presShell->GetPrimaryFrameFor(this);
if (frame) {
presShell->ScrollFrameIntoView(frame, NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE,
NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE);
}
aPresContext->EventStateManager()->SetContentState(this,
NS_EVENT_STATE_FOCUS)) {
presShell->ScrollContentIntoView(this, NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE,
NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE);
}
}

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

@ -1172,28 +1172,17 @@ nsGenericHTMLElement::ScrollIntoView(PRBool aTop)
return NS_OK;
}
// Flush all pending notifications so that our frames are up to date. Make
// sure to do this first thing, since it may end up destroying our document's
// presshell.
document->FlushPendingNotifications(Flush_Layout);
// Get the presentation shell
nsIPresShell *presShell = document->GetShellAt(0);
nsCOMPtr<nsIPresShell> presShell = document->GetShellAt(0);
if (!presShell) {
return NS_OK;
}
// Get the primary frame for this element
nsIFrame *frame = presShell->GetPrimaryFrameFor(this);
if (!frame) {
return NS_OK;
}
PRIntn vpercent = aTop ? NS_PRESSHELL_SCROLL_TOP :
NS_PRESSHELL_SCROLL_ANYWHERE;
presShell->ScrollFrameIntoView(frame, vpercent,
NS_PRESSHELL_SCROLL_ANYWHERE);
presShell->ScrollContentIntoView(this, vpercent,
NS_PRESSHELL_SCROLL_ANYWHERE);
return NS_OK;
}

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

@ -240,20 +240,10 @@ nsHTMLAnchorElement::SetFocus(nsPresContext* aPresContext)
nsILinkHandler *handler = aPresContext->GetLinkHandler();
if (handler && aPresContext->EventStateManager()->
SetContentState(this, NS_EVENT_STATE_FOCUS)) {
// Make sure the presentation is up-to-date
nsIDocument* doc = GetCurrentDoc();
if (doc) {
doc->FlushPendingNotifications(Flush_Layout);
}
nsIPresShell *presShell = aPresContext->GetPresShell();
nsCOMPtr<nsIPresShell> presShell = aPresContext->GetPresShell();
if (presShell) {
nsIFrame* frame = presShell->GetPrimaryFrameFor(this);
if (frame) {
presShell->ScrollFrameIntoView(frame, NS_PRESSHELL_SCROLL_ANYWHERE,
NS_PRESSHELL_SCROLL_ANYWHERE);
}
presShell->ScrollContentIntoView(this, NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE,
NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE);
}
}
}

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

@ -196,21 +196,10 @@ nsHTMLAreaElement::SetFocus(nsPresContext* aPresContext)
NS_EVENT_STATE_FOCUS)) {
return;
}
// Make sure the presentation is up-to-date
nsIDocument* doc = GetCurrentDoc();
if (doc) {
doc->FlushPendingNotifications(Flush_Layout);
}
nsIPresShell *presShell = aPresContext->GetPresShell();
nsCOMPtr<nsIPresShell> presShell = aPresContext->GetPresShell();
if (presShell) {
nsIFrame* frame = presShell->GetPrimaryFrameFor(this);
if (frame) {
presShell->ScrollFrameIntoView(frame, NS_PRESSHELL_SCROLL_ANYWHERE,
presShell->ScrollContentIntoView(this, NS_PRESSHELL_SCROLL_ANYWHERE,
NS_PRESSHELL_SCROLL_ANYWHERE);
}
}
}

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

@ -2622,17 +2622,10 @@ NS_IMETHODIMP DocumentViewerImpl::ScrollToNode(nsIDOMNode* aNode)
nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
// Get the primary frame
// Remember Frames aren't ref-counted. They are in their own special little
// world.
nsIFrame* frame = presShell->GetPrimaryFrameFor(content);
NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
// tell the pres shell to scroll to the frame
NS_ENSURE_SUCCESS(presShell->ScrollFrameIntoView(frame,
NS_PRESSHELL_SCROLL_TOP,
NS_PRESSHELL_SCROLL_ANYWHERE),
// Tell the PresShell to scroll to the primary frame of the content.
NS_ENSURE_SUCCESS(presShell->ScrollContentIntoView(content,
NS_PRESSHELL_SCROLL_TOP,
NS_PRESSHELL_SCROLL_ANYWHERE),
NS_ERROR_FAILURE);
return NS_OK;
}

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

@ -98,12 +98,12 @@ class nsIScrollableFrame;
typedef short SelectionType;
// 7C398278-8523-4E5C-8268-4E4BC8B0C5CA
//12f7a744-26d8-493e-8072-90123a35f69f
#define NS_IPRESSHELL_IID \
{ 0x7C398278, 0x8523, 0x4E5C, \
{ 0x82, 0x68, 0x4E, 0x4B, 0xC8, 0xB0, 0xC5, 0xCA } }
{ 0x12f7a744, 0x26d8, 0x493e, \
{ 0x80, 0x72, 0x90, 0x12, 0x3a, 0x35, 0xf6, 0x9f } }
// Constants uses for ScrollFrameIntoView() function
// Constants for ScrollFrameIntoView() and ScrollContentIntoView() functions.
#define NS_PRESSHELL_SCROLL_TOP 0
#define NS_PRESSHELL_SCROLL_BOTTOM 100
#define NS_PRESSHELL_SCROLL_LEFT 0
@ -441,6 +441,17 @@ public:
PRIntn aVPercent,
PRIntn aHPercent) const = 0;
/**
* Otherwise same as the above, but takes an aContent as the first parameter
* and after flushing pending notifications tries to find primary frame
* for that and then call ScrollFrameIntoView.
* @param aContent The content object of which primary frame should be
* scrolled into view.
*/
NS_IMETHOD ScrollContentIntoView(nsIContent* aContent,
PRIntn aVPercent,
PRIntn aHPercent) const = 0;
/**
* Suppress notification of the frame manager that frames are
* being destroyed.

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

@ -859,6 +859,10 @@ public:
PRIntn aVPercent,
PRIntn aHPercent) const;
NS_IMETHOD ScrollContentIntoView(nsIContent* aContent,
PRIntn aVPercent,
PRIntn aHPercent) const;
NS_IMETHOD SetIgnoreFrameDestruction(PRBool aIgnore);
NS_IMETHOD NotifyDestroyingFrame(nsIFrame* aFrame);
@ -3731,12 +3735,8 @@ PresShell::GoToAnchor(const nsAString& aAnchorName, PRBool aScroll)
if (content) {
// Flush notifications so we scroll to the right place
if (aScroll) {
mDocument->FlushPendingNotifications(Flush_Layout);
// Get the primary frame
nsIFrame* frame = GetPrimaryFrameFor(content);
NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
rv = ScrollFrameIntoView(frame, NS_PRESSHELL_SCROLL_TOP,
NS_PRESSHELL_SCROLL_ANYWHERE);
rv = ScrollContentIntoView(content, NS_PRESSHELL_SCROLL_TOP,
NS_PRESSHELL_SCROLL_ANYWHERE);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -4047,6 +4047,19 @@ PresShell::ScrollFrameIntoView(nsIFrame *aFrame,
return NS_OK;
}
NS_IMETHODIMP
PresShell::ScrollContentIntoView(nsIContent* aContent,
PRIntn aVPercent,
PRIntn aHPercent) const
{
nsCOMPtr<nsIContent> content = aContent; // Keep content alive while flushing.
NS_ENSURE_TRUE(content, NS_ERROR_NULL_POINTER);
nsCOMPtr<nsIDocument> currentDoc = content->GetCurrentDoc();
NS_ENSURE_STATE(currentDoc);
currentDoc->FlushPendingNotifications(Flush_Layout);
return ScrollFrameIntoView(GetPrimaryFrameFor(content), aVPercent, aHPercent);
}
// GetLinkLocation: copy link location to clipboard
NS_IMETHODIMP PresShell::GetLinkLocation(nsIDOMNode* aNode, nsAString& aLocationString)
{

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

@ -192,14 +192,11 @@ inFlasher::ScrollElementIntoView(nsIDOMElement *aElement)
if (!presShell) {
return NS_OK;
}
nsIFrame* frame = inLayoutUtils::GetFrameFor(aElement, presShell);
if (!frame) {
return NS_OK;
}
presShell->ScrollFrameIntoView(frame,
NS_PRESSHELL_SCROLL_ANYWHERE /* VPercent */,
NS_PRESSHELL_SCROLL_ANYWHERE /* HPercent */);
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
presShell->ScrollContentIntoView(content,
NS_PRESSHELL_SCROLL_ANYWHERE /* VPercent */,
NS_PRESSHELL_SCROLL_ANYWHERE /* HPercent */);
return NS_OK;
}

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

@ -224,9 +224,7 @@ nsFormFillController::SetPopupOpen(PRBool aPopupOpen)
nsCOMPtr<nsIPresShell> presShell;
docShell->GetPresShell(getter_AddRefs(presShell));
NS_ENSURE_STATE(presShell);
nsIFrame *frame = presShell->GetPrimaryFrameFor(content.get());
if (frame)
presShell->ScrollFrameIntoView(frame,
presShell->ScrollContentIntoView(content,
NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE,
NS_PRESSHELL_SCROLL_IF_NOT_VISIBLE);