Make the listbox box object deal better with the frame being destroyed and

change the tree box object the same way.  Bug 282105, bug 325045, bug 322513.
r=neil, sr=ben
This commit is contained in:
bzbarsky%mit.edu 2006-01-30 21:29:10 +00:00
parent d510542406
commit a8ab56ce86
10 changed files with 200 additions and 68 deletions

View File

@ -284,7 +284,7 @@ static FrameCtorDebugFlags gFlags[] = {
#include "nsPopupSetFrame.h"
#include "nsTreeColFrame.h"
#include "nsIBoxObject.h"
#include "nsIListBoxObject.h"
#include "nsPIListBoxObject.h"
#include "nsListBoxBodyFrame.h"
#include "nsListItemFrame.h"
@ -9296,10 +9296,9 @@ PRBool NotifyListBoxBody(nsPresContext* aPresContext,
nsCOMPtr<nsIDOMXULElement> xulElement = do_QueryInterface(aContainer);
nsCOMPtr<nsIBoxObject> boxObject;
xulElement->GetBoxObject(getter_AddRefs(boxObject));
nsCOMPtr<nsIListBoxObject> listBoxObject = do_QueryInterface(boxObject);
nsCOMPtr<nsPIListBoxObject> listBoxObject = do_QueryInterface(boxObject);
if (listBoxObject) {
nsIListBoxObject* listboxBody;
listBoxObject->GetListboxBody(&listboxBody);
nsIListBoxObject* listboxBody = listBoxObject->GetListBoxBody();
if (listboxBody) {
nsListBoxBodyFrame *listBoxBodyFrame = NS_STATIC_CAST(nsListBoxBodyFrame*, listboxBody);
if (aOperation == CONTENT_REMOVED)

View File

@ -44,6 +44,8 @@ interface nsIDOMElement;
[scriptable, uuid(FDE7C970-0B4E-49f4-B1EB-974AE6C96336)]
interface nsIListBoxObject : nsISupports
{
// listboxBody is always null. It's only here to avoid changing the
// interface.
readonly attribute nsIListBoxObject listboxBody;
long getRowCount();

View File

@ -402,6 +402,17 @@ nsBoxObject::GetPropertyAsSupports(const PRUnichar* aPropertyName, nsISupports**
NS_IMETHODIMP
nsBoxObject::SetPropertyAsSupports(const PRUnichar* aPropertyName, nsISupports* aValue)
{
#ifdef DEBUG
if (aValue) {
nsIFrame* frame;
CallQueryInterface(aValue, &frame);
NS_ASSERTION(!frame,
"Calling SetPropertyAsSupports on a frame. Prepare to crash "
"and be exploited any time some random website decides to "
"exploit you");
}
#endif
if (!mPresState)
NS_NewPresState(getter_Transfers(mPresState));

View File

@ -71,6 +71,7 @@
#include "nsPIBoxObject.h"
#include "nsINodeInfo.h"
#include "nsLayoutUtils.h"
#include "nsPIListBoxObject.h"
/////////////// nsListScrollSmoother //////////////////
@ -283,10 +284,9 @@ nsListBoxBodyFrame::Destroy(nsPresContext* aPresContext)
nsCOMPtr<nsIBoxObject> box;
nsdoc->GetBoxObjectFor(e, getter_AddRefs(box));
nsCOMPtr<nsPIBoxObject> pibox(do_QueryInterface(box));
if (pibox) {
pibox->InvalidatePresentationStuff();
nsCOMPtr<nsPIListBoxObject> piBox = do_QueryInterface(box);
if (piBox) {
piBox->ClearCachedListBoxBody();
}
break;

View File

@ -38,7 +38,7 @@
* ***** END LICENSE BLOCK ***** */
#include "nsCOMPtr.h"
#include "nsIListBoxObject.h"
#include "nsPIListBoxObject.h"
#include "nsBoxObject.h"
#include "nsIFrame.h"
#include "nsIDocument.h"
@ -48,41 +48,30 @@
#include "nsXULAtoms.h"
#include "nsIScrollableFrame.h"
class nsListBoxObject : public nsIListBoxObject, public nsBoxObject
class nsListBoxObject : public nsPIListBoxObject, public nsBoxObject
{
public:
NS_DECL_ISUPPORTS
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSILISTBOXOBJECT
// nsPIListBoxObject
virtual void ClearCachedListBoxBody();
virtual nsIListBoxObject* GetListBoxBody();
nsListBoxObject();
virtual ~nsListBoxObject();
nsIListBoxObject* GetListBoxBody();
NS_IMETHOD InvalidatePresentationStuff();
protected:
nsIListBoxObject* mListBoxBody;
};
NS_IMPL_ADDREF(nsListBoxObject)
NS_IMPL_RELEASE(nsListBoxObject)
NS_IMPL_ISUPPORTS_INHERITED2(nsListBoxObject, nsBoxObject, nsIListBoxObject,
nsPIListBoxObject);
NS_IMETHODIMP
nsListBoxObject::QueryInterface(REFNSIID iid, void** aResult)
{
if (!aResult)
return NS_ERROR_NULL_POINTER;
if (iid.Equals(NS_GET_IID(nsIListBoxObject))) {
*aResult = (nsIListBoxObject*)this;
NS_ADDREF(this);
return NS_OK;
}
return nsBoxObject::QueryInterface(iid, aResult);
}
nsListBoxObject::nsListBoxObject()
: mListBoxBody(nsnull)
{
}
@ -97,8 +86,7 @@ nsListBoxObject::~nsListBoxObject()
NS_IMETHODIMP
nsListBoxObject::GetListboxBody(nsIListBoxObject * *aListboxBody)
{
*aListboxBody = GetListBoxBody();
NS_IF_ADDREF(*aListboxBody);
*aListboxBody = nsnull;
return NS_OK;
}
@ -175,6 +163,12 @@ nsListBoxObject::GetIndexOfItem(nsIDOMElement* aElement, PRInt32 *aResult)
return NS_OK;
}
void
nsListBoxObject::ClearCachedListBoxBody()
{
mListBoxBody = nsnull;
}
//////////////////////
static void
@ -206,14 +200,8 @@ FindBodyContent(nsIContent* aParent, nsIContent** aResult)
nsIListBoxObject*
nsListBoxObject::GetListBoxBody()
{
NS_NAMED_LITERAL_STRING(listboxbody, "listboxbody");
nsCOMPtr<nsISupports> supp;
GetPropertyAsSupports(listboxbody.get(), getter_AddRefs(supp));
if (supp) {
nsCOMPtr<nsIListBoxObject> body(do_QueryInterface(supp));
return body;
if (mListBoxBody) {
return mListBoxBody;
}
nsIFrame* frame = GetFrame();
@ -239,16 +227,14 @@ nsListBoxObject::GetListBoxBody()
return nsnull;
// It's a frame. Refcounts are irrelevant.
nsCOMPtr<nsIListBoxObject> body;
yeahBaby->QueryInterface(NS_GET_IID(nsIListBoxObject), getter_AddRefs(body));
SetPropertyAsSupports(listboxbody.get(), body);
return body;
CallQueryInterface(yeahBaby, &mListBoxBody);
return mListBoxBody;
}
NS_IMETHODIMP
nsListBoxObject::InvalidatePresentationStuff()
{
SetPropertyAsSupports(NS_LITERAL_STRING("listboxbody").get(), nsnull);
ClearCachedListBoxBody();
return nsBoxObject::InvalidatePresentationStuff();
}

View File

@ -0,0 +1,65 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.org code.
*
* The Initial Developer of the Original Code is Mozilla.org.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Boris Zbarsky <bzbarsky@mit.edu> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsPIListBoxObject_h__
#define nsPIListBoxObject_h__
#define NS_PILISTBOXOBJECT_IID \
{ 0x294e0820, 0x5c40, 0x42a8, \
{ 0xb3, 0x2f, 0x6d, 0xcf, 0x05, 0xfb, 0xe1, 0xf3 } }
#include "nsIListBoxObject.h"
class nsPIListBoxObject : public nsIListBoxObject {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_PILISTBOXOBJECT_IID)
/**
* Clear the cached list box body frame from this box object. This should be
* called when the frame in question is destroyed.
*/
virtual void ClearCachedListBoxBody() = 0;
/*
* Get the list box body. This will search for it as needed.
*/
virtual nsIListBoxObject* GetListBoxBody() = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsPIListBoxObject, NS_PILISTBOXOBJECT_IID)
#endif // nsPIListBoxObject_h__

View File

@ -0,0 +1,60 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.org code.
*
* The Initial Developer of the Original Code is Mozilla.org.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Boris Zbarsky <bzbarsky@mit.edu> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsPITreeBoxObject_h__
#define nsPITreeBoxObject_h__
#define NS_PITREEBOXOBJECT_IID \
{ 0xafcd2a82, 0xc484, 0x4f86, \
{ 0x83, 0x77, 0xd9, 0xb8, 0x59, 0x31, 0xef, 0xf0 } }
#include "nsITreeBoxObject.h"
class nsPITreeBoxObject : public nsITreeBoxObject {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_PITREEBOXOBJECT_IID)
/**
* Clear the cached tree body frame from this box object. This should be
* called when the frame in question is destroyed.
*/
virtual void ClearCachedTreeBody() = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsPITreeBoxObject, NS_PITREEBOXOBJECT_IID)
#endif // nsPITreeBoxObject_h__

View File

@ -144,7 +144,7 @@ NS_INTERFACE_MAP_END_INHERITING(nsLeafBoxFrame)
// Constructor
nsTreeBodyFrame::nsTreeBodyFrame(nsIPresShell* aPresShell)
:nsLeafBoxFrame(aPresShell), mTreeBoxObject(nsnull),
:nsLeafBoxFrame(aPresShell),
mScrollbar(nsnull), mHorzScrollbar(nsnull), mColScrollContent(nsnull), mColScrollView(nsnull),
mHorzPosition(0), mHorzWidth(0), mRowHeight(0), mIndentation(0), mStringWidth(-1),
mTopRowIndex(0), mFocused(PR_FALSE), mHasFixedRowCount(PR_FALSE),
@ -355,8 +355,7 @@ nsTreeBodyFrame::Destroy(nsPresContext* aPresContext)
}
// Always null out the cached tree body frame.
nsAutoString treeBody(NS_LITERAL_STRING("treebody"));
box->RemoveProperty(treeBody.get());
mTreeBoxObject->ClearCachedTreeBody();
mTreeBoxObject = nsnull; // Drop our ref here.
}
@ -402,12 +401,14 @@ nsTreeBodyFrame::EnsureView()
nsCOMPtr<nsIBoxObject> box = do_QueryInterface(mTreeBoxObject);
if (box) {
nsCOMPtr<nsISupports> suppView;
box->GetPropertyAsSupports(NS_LITERAL_STRING("view").get(), getter_AddRefs(suppView));
box->GetPropertyAsSupports(NS_LITERAL_STRING("view").get(),
getter_AddRefs(suppView));
nsCOMPtr<nsITreeView> treeView(do_QueryInterface(suppView));
if (treeView) {
nsXPIDLString rowStr;
box->GetProperty(NS_LITERAL_STRING("topRow").get(), getter_Copies(rowStr));
box->GetProperty(NS_LITERAL_STRING("topRow").get(),
getter_Copies(rowStr));
nsAutoString rowStr2(rowStr);
PRInt32 error;
PRInt32 rowIndex = rowStr2.ToInteger(&error);
@ -524,7 +525,7 @@ NS_IMETHODIMP nsTreeBodyFrame::SetView(nsITreeView * aView)
EnsureBoxObject();
nsCOMPtr<nsIBoxObject> box = do_QueryInterface(mTreeBoxObject);
nsAutoString view(NS_LITERAL_STRING("view"));
NS_NAMED_LITERAL_STRING(view, "view");
if (mView) {
nsCOMPtr<nsITreeSelection> sel;

View File

@ -41,7 +41,7 @@
* ***** END LICENSE BLOCK ***** */
#include "nsLeafBoxFrame.h"
#include "nsITreeBoxObject.h"
#include "nsPITreeBoxObject.h"
#include "nsITreeView.h"
#include "nsICSSPseudoComparator.h"
#include "nsIScrollbarMediator.h"
@ -343,7 +343,7 @@ protected:
protected: // Data Members
// The cached box object parent.
nsCOMPtr<nsITreeBoxObject> mTreeBoxObject;
nsCOMPtr<nsPITreeBoxObject> mTreeBoxObject;
// Cached column information.
nsRefPtr<nsTreeColumns> mColumns;

View File

@ -40,7 +40,7 @@
#include "nsCOMPtr.h"
#include "nsPresContext.h"
#include "nsIPresShell.h"
#include "nsITreeBoxObject.h"
#include "nsPITreeBoxObject.h"
#include "nsITreeView.h"
#include "nsITreeSelection.h"
#include "nsBoxObject.h"
@ -50,7 +50,7 @@
#include "nsXULAtoms.h"
#include "nsChildIterator.h"
class nsTreeBoxObject : public nsITreeBoxObject, public nsBoxObject
class nsTreeBoxObject : public nsPITreeBoxObject, public nsBoxObject
{
public:
NS_DECL_ISUPPORTS_INHERITED
@ -65,10 +65,17 @@ public:
NS_IMETHOD Init(nsIContent* aContent, nsIPresShell* aPresShell);
NS_IMETHOD SetDocument(nsIDocument* aDocument);
NS_IMETHOD InvalidatePresentationStuff();
// nsPITreeBoxObject
virtual void ClearCachedTreeBody();
protected:
nsITreeBoxObject* mTreeBody;
};
/* Implementation file */
NS_IMPL_ISUPPORTS_INHERITED1(nsTreeBoxObject, nsBoxObject, nsITreeBoxObject)
NS_IMPL_ISUPPORTS_INHERITED2(nsTreeBoxObject, nsBoxObject, nsITreeBoxObject,
nsPITreeBoxObject)
NS_IMETHODIMP
@ -97,13 +104,14 @@ nsTreeBoxObject::SetDocument(nsIDocument* aDocument)
NS_IMETHODIMP
nsTreeBoxObject::InvalidatePresentationStuff()
{
SetPropertyAsSupports(NS_LITERAL_STRING("treebody").get(), nsnull);
ClearCachedTreeBody();
SetPropertyAsSupports(NS_LITERAL_STRING("view").get(), nsnull);
return nsBoxObject::InvalidatePresentationStuff();
}
nsTreeBoxObject::nsTreeBoxObject()
: mTreeBody(nsnull)
{
}
@ -142,15 +150,11 @@ static void FindBodyElement(nsIContent* aParent, nsIContent** aResult)
}
}
inline nsITreeBoxObject*
nsITreeBoxObject*
nsTreeBoxObject::GetTreeBody()
{
nsCOMPtr<nsISupports> supp;
GetPropertyAsSupports(NS_LITERAL_STRING("treebody").get(), getter_AddRefs(supp));
if (supp) {
nsCOMPtr<nsITreeBoxObject> body(do_QueryInterface(supp));
return body;
if (mTreeBody) {
return mTreeBody;
}
nsIFrame* frame = GetFrame();
@ -166,10 +170,8 @@ nsTreeBoxObject::GetTreeBody()
return nsnull;
// It's a frame. Refcounts are irrelevant.
nsCOMPtr<nsITreeBoxObject> body;
frame->QueryInterface(NS_GET_IID(nsITreeBoxObject), getter_AddRefs(body));
SetPropertyAsSupports(NS_LITERAL_STRING("treebody").get(), body);
return body;
CallQueryInterface(frame, &mTreeBody);
return mTreeBody;
}
NS_IMETHODIMP nsTreeBoxObject::GetView(nsITreeView * *aView)
@ -464,6 +466,12 @@ NS_IMETHODIMP nsTreeBoxObject::ClearStyleAndImageCaches()
return NS_OK;
}
void
nsTreeBoxObject::ClearCachedTreeBody()
{
mTreeBody = nsnull;
}
// Creation Routine ///////////////////////////////////////////////////////////////////////
nsresult