Fix for bug 471126 (leak content nodes (and sometimes dom windows) after clicking on nytimes.com articles). r=bent, sr=bz.

This commit is contained in:
Peter Van der Beken 2009-01-14 13:24:10 +01:00
Родитель 1a76d6b1c6
Коммит 2353ea8945
7 изменённых файлов: 189 добавлений и 115 удалений

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

@ -54,8 +54,7 @@
#include "nsITransactionManager.h"
nsComposerCommandsUpdater::nsComposerCommandsUpdater()
: mDOMWindow(nsnull)
, mDirtyState(eStateUninitialized)
: mDirtyState(eStateUninitialized)
, mSelectionCollapsed(eStateUninitialized)
, mFirstDoOfFirstUndo(PR_TRUE)
{
@ -63,6 +62,11 @@ nsComposerCommandsUpdater::nsComposerCommandsUpdater()
nsComposerCommandsUpdater::~nsComposerCommandsUpdater()
{
// cancel any outstanding update timer
if (mUpdateTimer)
{
mUpdateTimer->Cancel();
}
}
NS_IMPL_ISUPPORTS4(nsComposerCommandsUpdater, nsISelectionListener,
@ -241,7 +245,7 @@ nsresult
nsComposerCommandsUpdater::Init(nsIDOMWindow* aDOMWindow)
{
NS_ENSURE_ARG(aDOMWindow);
mDOMWindow = aDOMWindow;
mDOMWindow = do_GetWeakReference(aDOMWindow);
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(aDOMWindow));
if (window)
@ -364,10 +368,12 @@ nsComposerCommandsUpdater::UpdateOneCommand(const char *aCommand)
PRBool
nsComposerCommandsUpdater::SelectionIsCollapsed()
{
if (!mDOMWindow) return PR_TRUE;
nsCOMPtr<nsIDOMWindow> domWindow = do_QueryReferent(mDOMWindow);
if (!domWindow)
return PR_TRUE;
nsCOMPtr<nsISelection> domSelection;
if (NS_SUCCEEDED(mDOMWindow->GetSelection(getter_AddRefs(domSelection))) && domSelection)
if (NS_SUCCEEDED(domWindow->GetSelection(getter_AddRefs(domSelection))) && domSelection)
{
PRBool selectionCollapsed = PR_FALSE;
domSelection->GetIsCollapsed(&selectionCollapsed);

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

@ -119,7 +119,7 @@ protected:
void TimerCallback();
nsCOMPtr<nsITimer> mUpdateTimer;
nsIDOMWindow* mDOMWindow; // Weak reference
nsWeakPtr mDOMWindow;
nsWeakPtr mDocShell;
PRInt8 mDirtyState;
PRInt8 mSelectionCollapsed;

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

@ -393,6 +393,8 @@ private:
nsresult GetClipboardEventTarget(nsIDOMNode **aEventTarget);
nsresult FireClipboardEvent(PRUint32 msg, PRBool* aPreventDefault);
void DestroyPresShell();
#ifdef NS_PRINTING
// Called when the DocViewer is notified that the state
// of Printing or PP has changed
@ -674,6 +676,9 @@ DocumentViewerImpl::Init(nsIWidget* aParentWidget,
nsresult
DocumentViewerImpl::InitPresentationStuff(PRBool aDoInitialReflow, PRBool aReenableRefresh)
{
NS_ASSERTION(!mPresShell,
"Someone should have destroyed the presshell!");
// Create the style set...
nsStyleSet *styleSet;
nsresult rv = CreateStyleSet(mDocument, &styleSet);
@ -747,14 +752,16 @@ DocumentViewerImpl::InitPresentationStuff(PRBool aDoInitialReflow, PRBool aReena
// now register ourselves as a selection listener, so that we get
// called when the selection changes in the window
nsDocViewerSelectionListener *selectionListener =
new nsDocViewerSelectionListener();
NS_ENSURE_TRUE(selectionListener, NS_ERROR_OUT_OF_MEMORY);
if (!mSelectionListener) {
nsDocViewerSelectionListener *selectionListener =
new nsDocViewerSelectionListener();
NS_ENSURE_TRUE(selectionListener, NS_ERROR_OUT_OF_MEMORY);
selectionListener->Init(this);
selectionListener->Init(this);
// mSelectionListener is a owning reference
mSelectionListener = selectionListener;
// mSelectionListener is a owning reference
mSelectionListener = selectionListener;
}
nsCOMPtr<nsISelection> selection;
rv = GetDocumentSelection(getter_AddRefs(selection));
@ -1515,19 +1522,7 @@ DocumentViewerImpl::Destroy()
mDeviceContext = nsnull;
if (mPresShell) {
// Break circular reference (or something)
mPresShell->EndObservingDocument();
nsCOMPtr<nsISelection> selection;
GetDocumentSelection(getter_AddRefs(selection));
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(selection));
if (selPrivate && mSelectionListener)
selPrivate->RemoveSelectionListener(mSelectionListener);
mPresShell->Destroy();
mPresShell = nsnull;
DestroyPresShell();
}
if (mPresContext) {
@ -1640,10 +1635,7 @@ DocumentViewerImpl::SetDOMDocument(nsIDOMDocument *aDocument)
linkHandler = mPresContext->GetLinkHandler();
}
mPresShell->EndObservingDocument();
mPresShell->Destroy();
mPresShell = nsnull;
DestroyPresShell();
// This destroys the root view because it was associated with the root frame,
// which has been torn down. Recreate the viewmanager and root view.
@ -1954,30 +1946,18 @@ DocumentViewerImpl::Hide(void)
return NS_OK;
}
// Break circular reference (or something)
mPresShell->EndObservingDocument();
nsCOMPtr<nsISelection> selection;
GetDocumentSelection(getter_AddRefs(selection));
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(selection));
if (selPrivate && mSelectionListener) {
selPrivate->RemoveSelectionListener(mSelectionListener);
}
nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mContainer));
if (docShell) {
nsCOMPtr<nsILayoutHistoryState> layoutState;
mPresShell->CaptureHistoryState(getter_AddRefs(layoutState), PR_TRUE);
}
mPresShell->Destroy();
DestroyPresShell();
// Clear weak refs
mPresContext->SetContainer(nsnull);
mPresContext->SetLinkHandler(nsnull);
mPresShell = nsnull;
mPresContext = nsnull;
mViewManager = nsnull;
mWindow = nsnull;
@ -4166,14 +4146,7 @@ NS_IMETHODIMP DocumentViewerImpl::SetPageMode(PRBool aPageMode, nsIPrintSettings
mWindow->GetBounds(bounds);
if (mPresShell) {
// Break circular reference (or something)
mPresShell->EndObservingDocument();
nsCOMPtr<nsISelection> selection;
nsresult rv = GetDocumentSelection(getter_AddRefs(selection));
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(selection));
if (NS_SUCCEEDED(rv) && selPrivate && mSelectionListener)
selPrivate->RemoveSelectionListener(mSelectionListener);
mPresShell->Destroy();
DestroyPresShell();
}
if (mPresContext) {
@ -4210,3 +4183,19 @@ DocumentViewerImpl::GetHistoryEntry(nsISHEntry **aHistoryEntry)
NS_IF_ADDREF(*aHistoryEntry = mSHEntry);
return NS_OK;
}
void
DocumentViewerImpl::DestroyPresShell()
{
// Break circular reference (or something)
mPresShell->EndObservingDocument();
nsCOMPtr<nsISelection> selection;
GetDocumentSelection(getter_AddRefs(selection));
nsCOMPtr<nsISelectionPrivate> selPrivate = do_QueryInterface(selection);
if (selPrivate && mSelectionListener)
selPrivate->RemoveSelectionListener(mSelectionListener);
mPresShell->Destroy();
mPresShell = nsnull;
}

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

@ -65,6 +65,7 @@ _TEST_FILES = \
test_bug450930.xhtml \
test_bug458898.html \
test_bug465448.xul \
test_bug471126.html \
$(NULL)
# test_bug396024.html is currently disabled because it interacts badly with
# the "You can't print-preview while the page is loading" dialog.

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

@ -0,0 +1,35 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=471126
-->
<head>
<title>Test for Bug 471126</title>
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=471126">Mozilla Bug 471126</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 471126 **/
function test()
{
var selection = window.getSelection();
selection.collapse(document.documentElement, 0);
document.documentElement.addEventListener("click", function(){ var foo = window; }, false);
}
test();
ok(true, "Shoudn't leak");
</script>
</pre>
</body>
</html>

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

@ -214,7 +214,8 @@ public:
enum HINT { HINTLEFT = 0, HINTRIGHT = 1}; //end of this line or beginning of next
/*interfaces for addref and release and queryinterface*/
NS_DECL_ISUPPORTS
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(nsFrameSelection)
/** Init will initialize the frame selector with the necessary pres shell to
* be used by most of the methods
@ -551,7 +552,6 @@ public:
nsFrameSelection();
virtual ~nsFrameSelection();
void StartBatchChanges();
void EndBatchChanges();
@ -615,7 +615,7 @@ private:
// so remember to use nsCOMPtr when needed.
nsresult NotifySelectionListeners(SelectionType aType); // add parameters to say collapsed etc?
nsTypedSelection *mDomSelections[nsISelectionController::NUM_SELECTIONTYPES];
nsRefPtr<nsTypedSelection> mDomSelections[nsISelectionController::NUM_SELECTIONTYPES];
// Table selection support.
// Interfaces that let us get info based on cellmap locations

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

@ -196,7 +196,8 @@ public:
nsTypedSelection(nsFrameSelection *aList);
virtual ~nsTypedSelection();
NS_DECL_ISUPPORTS
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsTypedSelection, nsISelection)
NS_DECL_NSISELECTION
NS_DECL_NSISELECTION2
NS_DECL_NSISELECTIONPRIVATE
@ -357,7 +358,7 @@ private:
nsTArray<RangeData> mRanges;
nsTArray<PRInt32> mRangeEndings; // references info mRanges
nsCOMPtr<nsIDOMRange> mAnchorFocusRange;
nsFrameSelection *mFrameSelection;
nsRefPtr<nsFrameSelection> mFrameSelection;
nsWeakPtr mPresShellWeak;
nsRefPtr<nsAutoScrollTimer> mAutoScrollTimer;
nsCOMArray<nsISelectionListener> mSelectionListeners;
@ -809,13 +810,10 @@ nsFrameSelection::nsFrameSelection()
mDelayedMouseEvent(PR_FALSE, 0, nsnull, nsMouseEvent::eReal)
{
PRInt32 i;
for (i = 0;i<nsISelectionController::NUM_SELECTIONTYPES;i++){
mDomSelections[i] = nsnull;
}
for (i = 0;i<nsISelectionController::NUM_SELECTIONTYPES;i++){
mDomSelections[i] = new nsTypedSelection(this);
if (!mDomSelections[i])
return;
break;
mDomSelections[i]->SetType(GetSelectionTypeFromIndex(i));
}
mBatching = 0;
@ -855,18 +853,43 @@ nsFrameSelection::nsFrameSelection()
}
nsFrameSelection::~nsFrameSelection()
{
NS_IMPL_CYCLE_COLLECTION_CLASS(nsFrameSelection)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsFrameSelection)
PRInt32 i;
for (i = 0;i<nsISelectionController::NUM_SELECTIONTYPES;i++){
if (mDomSelections[i]) {
delete mDomSelections[i];
}
for (i = 0; i < nsISelectionController::NUM_SELECTIONTYPES; ++i) {
tmp->mDomSelections[i] = nsnull;
}
}
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCellParent)
tmp->mSelectingTableCellMode = 0;
tmp->mDragSelectingCells = PR_FALSE;
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mStartSelectedCell)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mEndSelectedCell)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAppendStartSelectedCell)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mUnselectCellOnMouseUp)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mMaintainRange)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFrameSelection)
PRInt32 i;
for (i = 0; i < nsISelectionController::NUM_SELECTIONTYPES; ++i) {
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mDomSelections[i],
nsISelection)
}
NS_IMPL_ISUPPORTS1(nsFrameSelection, nsFrameSelection)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCellParent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mStartSelectedCell)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mEndSelectedCell)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mAppendStartSelectedCell)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mUnselectCellOnMouseUp)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mMaintainRange)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFrameSelection)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFrameSelection)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFrameSelection)
NS_INTERFACE_MAP_ENTRY(nsFrameSelection)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
nsresult
@ -1229,6 +1252,9 @@ nsFrameSelection::MoveCaret(PRUint32 aKeycode,
nscoord desiredX = 0; //we must keep this around and revalidate it when its just UP/DOWN
PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
if (!mDomSelections[index])
return NS_ERROR_NULL_POINTER;
nsresult result = mDomSelections[index]->GetIsCollapsed(&isCollapsed);
if (NS_FAILED(result))
return result;
@ -1625,6 +1651,8 @@ nsresult
nsFrameSelection::MaintainSelection(nsSelectionAmount aAmount)
{
PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
if (!mDomSelections[index])
return NS_ERROR_NULL_POINTER;
mMaintainedAmount = aAmount;
mMaintainRange = nsnull;
@ -1738,6 +1766,8 @@ nsFrameSelection::AdjustForMaintainedSelection(nsIContent *aContent,
return PR_FALSE;
PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
if (!mDomSelections[index])
return PR_FALSE;
nsCOMPtr<nsIDOMNode> rangeStartNode, rangeEndNode;
PRInt32 rangeStartOffset, rangeEndOffset;
@ -1886,6 +1916,9 @@ nsFrameSelection::StartAutoScrollTimer(nsIView *aView,
{
NS_ENSURE_STATE(mShell);
PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
if (!mDomSelections[index])
return NS_ERROR_NULL_POINTER;
return mDomSelections[index]->StartAutoScrollTimer(mShell->GetPresContext(),
aView, aPoint, aDelay);
}
@ -1894,6 +1927,9 @@ void
nsFrameSelection::StopAutoScrollTimer()
{
PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
if (!mDomSelections[index])
return;
mDomSelections[index]->StopAutoScrollTimer();
}
@ -1931,6 +1967,9 @@ nsFrameSelection::TakeFocus(nsIContent *aNewFocus,
mHint = aHint;
PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
if (!mDomSelections[index])
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMNode> domNode = do_QueryInterface(aNewFocus);
//traverse through document and unselect crap here
if (!aContinueSelection) {//single click? setting cursor down
@ -2408,7 +2447,7 @@ nsresult
nsFrameSelection::NotifySelectionListeners(SelectionType aType)
{
PRInt8 index = GetIndexFromSelectionType(aType);
if (index >=0)
if (index >=0 && mDomSelections[index])
{
return mDomSelections[index]->NotifySelectionListeners();
}
@ -2454,6 +2493,9 @@ nsresult
nsFrameSelection::ClearNormalSelection()
{
PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
if (!mDomSelections[index])
return NS_ERROR_NULL_POINTER;
return mDomSelections[index]->RemoveAllRanges();
}
@ -2487,6 +2529,9 @@ nsFrameSelection::HandleTableSelection(nsIContent *aParentContent, PRInt32 aCont
// we can be sure that anchorNode's offset always points to the
// selected cell
PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
if (!mDomSelections[index])
return NS_ERROR_NULL_POINTER;
mDomSelections[index]->SetDirection(eDirNext);
// Stack-class to wrap all table selection changes in
@ -2816,6 +2861,8 @@ nsFrameSelection::SelectBlockOfCells(nsIContent *aStartCell, nsIContent *aEndCel
// Drag selecting: remove selected cells outside of new block limits
PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
if (!mDomSelections[index])
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMNode> cellNode;
nsCOMPtr<nsIDOMRange> range;
@ -3066,6 +3113,9 @@ nsFrameSelection::GetFirstSelectedCellAndRange(nsIDOMNode **aCell,
nsCOMPtr<nsIDOMRange> firstRange;
PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
if (!mDomSelections[index])
return NS_ERROR_NULL_POINTER;
nsresult result = mDomSelections[index]->GetRangeAt(0, getter_AddRefs(firstRange));
if (NS_FAILED(result)) return result;
if (!firstRange) return NS_ERROR_FAILURE;
@ -3102,6 +3152,9 @@ nsFrameSelection::GetNextSelectedCellAndRange(nsIDOMNode **aCell,
PRInt32 rangeCount;
PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
if (!mDomSelections[index])
return NS_ERROR_NULL_POINTER;
nsresult result = mDomSelections[index]->GetRangeCount(&rangeCount);
if (NS_FAILED(result)) return result;
@ -3408,6 +3461,9 @@ nsFrameSelection::CreateAndAddRange(nsIDOMNode *aParentNode, PRInt32 aOffset)
if (NS_FAILED(result)) return result;
PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
if (!mDomSelections[index])
return NS_ERROR_NULL_POINTER;
return mDomSelections[index]->AddRange(range);
}
@ -3420,6 +3476,9 @@ nsFrameSelection::SetAncestorLimiter(nsIContent *aLimiter)
mAncestorLimiter = aLimiter;
PRInt8 index =
GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
if (!mDomSelections[index])
return;
if (!IsValidSelectionPoint(this, mDomSelections[index]->FetchFocusNode())) {
ClearNormalSelection();
if (mAncestorLimiter) {
@ -3447,6 +3506,9 @@ nsFrameSelection::DeleteFromDocument()
// before we do the delete.
PRBool isCollapsed;
PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
if (!mDomSelections[index])
return NS_ERROR_NULL_POINTER;
mDomSelections[index]->GetIsCollapsed( &isCollapsed);
if (isCollapsed)
{
@ -3531,8 +3593,7 @@ nsFrameSelection::GetDelayedCaretData()
// note: this can return a nil anchor node
nsTypedSelection::nsTypedSelection()
: mFrameSelection(nsnull)
, mCachedOffsetForFrame(nsnull)
: mCachedOffsetForFrame(nsnull)
, mDirection(eDirNext)
, mType(nsISelectionController::SELECTION_NORMAL)
{
@ -3561,13 +3622,27 @@ nsTypedSelection::~nsTypedSelection()
delete mCachedOffsetForFrame;
mCachedOffsetForFrame = nsnull;
}
mFrameSelection = nsnull;
}
// QueryInterface implementation for nsRange
NS_INTERFACE_MAP_BEGIN(nsTypedSelection)
NS_IMPL_CYCLE_COLLECTION_CLASS(nsTypedSelection)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsTypedSelection)
tmp->RemoveAllRanges();
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFrameSelection)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsTypedSelection)
{
PRUint32 i, count = tmp->mRanges.Length();
for (i = 0; i < count; ++i) {
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRanges[i].mRange)
}
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mAnchorFocusRange)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFrameSelection)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
// QueryInterface implementation for nsTypedSelection
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsTypedSelection)
NS_INTERFACE_MAP_ENTRY(nsISelection)
NS_INTERFACE_MAP_ENTRY(nsISelection2)
NS_INTERFACE_MAP_ENTRY(nsISelectionPrivate)
@ -3576,37 +3651,8 @@ NS_INTERFACE_MAP_BEGIN(nsTypedSelection)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(Selection)
NS_INTERFACE_MAP_END
NS_IMETHODIMP_(nsrefcnt)
nsTypedSelection::AddRef()
{
if (mFrameSelection) {
return mFrameSelection->AddRef();
}
NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt");
NS_ASSERT_OWNINGTHREAD(nsTypedSelection);
++mRefCnt;
NS_LOG_ADDREF(this, mRefCnt, "nsTypedSelection", sizeof(*this));
return mRefCnt;
}
NS_IMETHODIMP_(nsrefcnt)
nsTypedSelection::Release()
{
if (mFrameSelection) {
return mFrameSelection->Release();
}
NS_PRECONDITION(0 != mRefCnt, "dup release");
NS_ASSERT_OWNINGTHREAD(nsTypedSelection);
--mRefCnt;
NS_LOG_RELEASE(this, mRefCnt, "nsTypedSelection");
if (mRefCnt == 0) {
mRefCnt = 1; /* stabilize */
NS_DELETEXPCOM(this);
return 0;
}
return mRefCnt;
}
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsTypedSelection)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsTypedSelection)
NS_IMETHODIMP
nsTypedSelection::SetPresShell(nsIPresShell *aPresShell)
@ -4100,7 +4146,8 @@ nsTypedSelection::Clear(nsPresContext* aPresContext)
SetDirection(eDirNext);
// If this was an ATTENTION selection, change it back to normal now
if (mFrameSelection->GetDisplaySelection() ==
if (mFrameSelection &&
mFrameSelection->GetDisplaySelection() ==
nsISelectionController::SELECTION_ATTENTION) {
mFrameSelection->SetDisplaySelection(nsISelectionController::SELECTION_ON);
}
@ -4460,7 +4507,7 @@ nsTypedSelection::FindRangeGivenPoint(
NS_IMETHODIMP
nsTypedSelection::GetPrimaryFrameForRangeEndpoint(nsIDOMNode *aNode, PRInt32 aOffset, PRBool aIsEndNode, nsIFrame **aReturnFrame)
{
if (!aNode || !aReturnFrame)
if (!aNode || !aReturnFrame || !mFrameSelection)
return NS_ERROR_NULL_POINTER;
if (aOffset < 0)
@ -4930,7 +4977,8 @@ nsTypedSelection::GetFrameSelection(nsFrameSelection **aFrameSelection) {
NS_IMETHODIMP
nsTypedSelection::SetAncestorLimiter(nsIContent *aContent)
{
mFrameSelection->SetAncestorLimiter(aContent);
if (mFrameSelection)
mFrameSelection->SetAncestorLimiter(aContent);
return NS_OK;
}
@ -5476,8 +5524,7 @@ nsTypedSelection::Collapse(nsIDOMNode* aParentNode, PRInt32 aOffset)
Clear(presContext);
// Turn off signal for table selection
if (mFrameSelection)
mFrameSelection->ClearTableCellSelection();
mFrameSelection->ClearTableCellSelection();
nsCOMPtr<nsIDOMRange> range;
NS_NewRange(getter_AddRefs(range));
@ -5515,8 +5562,6 @@ nsTypedSelection::Collapse(nsIDOMNode* aParentNode, PRInt32 aOffset)
selectFrames(presContext, range,PR_TRUE);
if (NS_FAILED(result))
return result;
if (!mFrameSelection)
return NS_OK;//nothing to do
return mFrameSelection->NotifySelectionListeners(GetType());
}
@ -5939,8 +5984,6 @@ nsTypedSelection::Extend(nsIDOMNode* aParentNode, PRInt32 aOffset)
printf ("Sel. Extend set to null parent.\n");
}
#endif
if (!mFrameSelection)
return NS_OK;//nothing to do
return mFrameSelection->NotifySelectionListeners(GetType());
}