1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is the Mozilla browser.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications, Inc.
19 * Portions created by the Initial Developer are Copyright (C) 1999
20 * the Initial Developer. All Rights Reserved.
23 * Radha Kulkarni <radha@netscape.com>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
40 #define DEBUG_PAGE_CACHE
44 #include "nsSHEntry.h"
45 #include "nsXPIDLString.h"
46 #include "nsReadableUtils.h"
47 #include "nsIDocShellLoadInfo.h"
48 #include "nsIDocShellTreeItem.h"
49 #include "nsIDocument.h"
50 #include "nsIDOMDocument.h"
51 #include "nsAutoPtr.h"
52 #include "nsThreadUtils.h"
53 #include "nsIWebNavigation.h"
54 #include "nsISHistory.h"
55 #include "nsISHistoryInternal.h"
56 #include "nsDocShellEditorData.h"
57 #include "nsIDocShell.h"
59 namespace dom
= mozilla::dom
;
61 // Hardcode this to time out unused content viewers after 30 minutes
62 #define CONTENT_VIEWER_TIMEOUT_SECONDS 30*60
64 typedef nsExpirationTracker
<nsSHEntry
,3> HistoryTrackerBase
;
65 class HistoryTracker
: public HistoryTrackerBase
{
67 // Expire cached contentviewers after 20-30 minutes in the cache.
68 HistoryTracker() : HistoryTrackerBase((CONTENT_VIEWER_TIMEOUT_SECONDS
/2)*1000) {}
71 virtual void NotifyExpired(nsSHEntry
* aObj
) {
77 static HistoryTracker
*gHistoryTracker
= nsnull
;
78 static PRUint32 gEntryID
= 0;
79 static PRUint64 gEntryDocIdentifier
= 0;
81 nsresult
nsSHEntry::Startup()
83 gHistoryTracker
= new HistoryTracker();
84 return gHistoryTracker
? NS_OK
: NS_ERROR_OUT_OF_MEMORY
;
87 void nsSHEntry::Shutdown()
89 delete gHistoryTracker
;
90 gHistoryTracker
= nsnull
;
93 static void StopTrackingEntry(nsSHEntry
*aEntry
)
95 if (aEntry
->GetExpirationState()->IsTracked()) {
96 gHistoryTracker
->RemoveObject(aEntry
);
100 //*****************************************************************************
101 //*** nsSHEntry: Object Management
102 //*****************************************************************************
105 nsSHEntry::nsSHEntry()
108 , mPageIdentifier(mID
)
109 , mDocIdentifier(gEntryDocIdentifier
++)
110 , mScrollPositionX(0)
111 , mScrollPositionY(0)
112 , mIsFrameNavigation(PR_FALSE
)
113 , mSaveLayoutState(PR_TRUE
)
116 , mDynamicallyCreated(PR_FALSE
)
118 , mViewerBounds(0, 0, 0, 0)
124 nsSHEntry::nsSHEntry(const nsSHEntry
&other
)
126 , mReferrerURI(other
.mReferrerURI
)
127 // XXX why not copy mDocument?
128 , mTitle(other
.mTitle
)
129 , mPostData(other
.mPostData
)
130 , mLayoutHistoryState(other
.mLayoutHistoryState
)
131 , mLoadType(0) // XXX why not copy?
133 , mPageIdentifier(other
.mPageIdentifier
)
134 , mDocIdentifier(other
.mDocIdentifier
)
135 , mScrollPositionX(0) // XXX why not copy?
136 , mScrollPositionY(0) // XXX why not copy?
137 , mIsFrameNavigation(other
.mIsFrameNavigation
)
138 , mSaveLayoutState(other
.mSaveLayoutState
)
139 , mExpired(other
.mExpired
)
141 , mDynamicallyCreated(other
.mDynamicallyCreated
)
142 // XXX why not copy mContentType?
143 , mCacheKey(other
.mCacheKey
)
144 , mParent(other
.mParent
)
145 , mViewerBounds(0, 0, 0, 0)
146 , mOwner(other
.mOwner
)
147 , mStateData(other
.mStateData
)
148 , mDocShellID(other
.mDocShellID
)
153 ClearParentPtr(nsISHEntry
* aEntry
, void* /* aData */)
156 aEntry
->SetParent(nsnull
);
161 nsSHEntry::~nsSHEntry()
163 StopTrackingEntry(this);
165 // Since we never really remove kids from SHEntrys, we need to null
166 // out the mParent pointers on all our kids.
167 mChildren
.EnumerateForwards(ClearParentPtr
, nsnull
);
170 if (mContentViewer
) {
171 // RemoveFromBFCacheSync is virtual, so call the nsSHEntry version
173 nsSHEntry::RemoveFromBFCacheSync();
176 mEditorData
= nsnull
;
179 // This is not happening as far as I can tell from breakpad as of early November 2007
180 nsExpirationTracker
<nsSHEntry
,3>::Iterator
iterator(gHistoryTracker
);
182 while ((elem
= iterator
.Next()) != nsnull
) {
183 NS_ASSERTION(elem
!= this, "Found dead entry still in the tracker!");
188 //*****************************************************************************
189 // nsSHEntry: nsISupports
190 //*****************************************************************************
192 NS_IMPL_ISUPPORTS5(nsSHEntry
, nsISHContainer
, nsISHEntry
, nsIHistoryEntry
,
193 nsIMutationObserver
, nsISHEntryInternal
)
195 //*****************************************************************************
196 // nsSHEntry: nsISHEntry
197 //*****************************************************************************
199 NS_IMETHODIMP
nsSHEntry::SetScrollPosition(PRInt32 x
, PRInt32 y
)
201 mScrollPositionX
= x
;
202 mScrollPositionY
= y
;
206 NS_IMETHODIMP
nsSHEntry::GetScrollPosition(PRInt32
*x
, PRInt32
*y
)
208 *x
= mScrollPositionX
;
209 *y
= mScrollPositionY
;
213 NS_IMETHODIMP
nsSHEntry::GetURI(nsIURI
** aURI
)
220 NS_IMETHODIMP
nsSHEntry::SetURI(nsIURI
* aURI
)
226 NS_IMETHODIMP
nsSHEntry::GetReferrerURI(nsIURI
**aReferrerURI
)
228 *aReferrerURI
= mReferrerURI
;
229 NS_IF_ADDREF(*aReferrerURI
);
233 NS_IMETHODIMP
nsSHEntry::SetReferrerURI(nsIURI
*aReferrerURI
)
235 mReferrerURI
= aReferrerURI
;
240 nsSHEntry::SetContentViewer(nsIContentViewer
*aViewer
)
242 NS_PRECONDITION(!aViewer
|| !mContentViewer
, "SHEntry already contains viewer");
244 if (mContentViewer
|| !aViewer
) {
245 DropPresentationState();
248 mContentViewer
= aViewer
;
250 if (mContentViewer
) {
251 gHistoryTracker
->AddObject(this);
253 nsCOMPtr
<nsIDOMDocument
> domDoc
;
254 mContentViewer
->GetDOMDocument(getter_AddRefs(domDoc
));
255 // Store observed document in strong pointer in case it is removed from
257 mDocument
= do_QueryInterface(domDoc
);
259 mDocument
->SetBFCacheEntry(this);
260 mDocument
->AddMutationObserver(this);
268 nsSHEntry::GetContentViewer(nsIContentViewer
**aResult
)
270 *aResult
= mContentViewer
;
271 NS_IF_ADDREF(*aResult
);
276 nsSHEntry::GetAnyContentViewer(nsISHEntry
**aOwnerEntry
,
277 nsIContentViewer
**aResult
)
279 // Find a content viewer in the root node or any of its children,
280 // assuming that there is only one content viewer total in any one
282 GetContentViewer(aResult
);
284 #ifdef DEBUG_PAGE_CACHE
285 printf("Found content viewer\n");
288 NS_ADDREF(*aOwnerEntry
);
291 // The root SHEntry doesn't have a ContentViewer, so check child nodes
292 for (PRInt32 i
= 0; i
< mChildren
.Count(); i
++) {
293 nsISHEntry
* child
= mChildren
[i
];
295 #ifdef DEBUG_PAGE_CACHE
296 printf("Evaluating SHEntry child %d\n", i
);
298 child
->GetAnyContentViewer(aOwnerEntry
, aResult
);
308 nsSHEntry::SetSticky(PRBool aSticky
)
315 nsSHEntry::GetSticky(PRBool
*aSticky
)
321 NS_IMETHODIMP
nsSHEntry::GetTitle(PRUnichar
** aTitle
)
323 // Check for empty title...
324 if (mTitle
.IsEmpty() && mURI
) {
325 // Default title is the URL.
327 if (NS_SUCCEEDED(mURI
->GetSpec(spec
)))
328 AppendUTF8toUTF16(spec
, mTitle
);
331 *aTitle
= ToNewUnicode(mTitle
);
335 NS_IMETHODIMP
nsSHEntry::SetTitle(const nsAString
&aTitle
)
341 NS_IMETHODIMP
nsSHEntry::GetPostData(nsIInputStream
** aResult
)
343 *aResult
= mPostData
;
344 NS_IF_ADDREF(*aResult
);
348 NS_IMETHODIMP
nsSHEntry::SetPostData(nsIInputStream
* aPostData
)
350 mPostData
= aPostData
;
354 NS_IMETHODIMP
nsSHEntry::GetLayoutHistoryState(nsILayoutHistoryState
** aResult
)
356 *aResult
= mLayoutHistoryState
;
357 NS_IF_ADDREF(*aResult
);
361 NS_IMETHODIMP
nsSHEntry::SetLayoutHistoryState(nsILayoutHistoryState
* aState
)
363 mLayoutHistoryState
= aState
;
364 if (mLayoutHistoryState
)
365 mLayoutHistoryState
->SetScrollPositionOnly(!mSaveLayoutState
);
370 NS_IMETHODIMP
nsSHEntry::GetLoadType(PRUint32
* aResult
)
372 *aResult
= mLoadType
;
376 NS_IMETHODIMP
nsSHEntry::SetLoadType(PRUint32 aLoadType
)
378 mLoadType
= aLoadType
;
382 NS_IMETHODIMP
nsSHEntry::GetID(PRUint32
* aResult
)
388 NS_IMETHODIMP
nsSHEntry::SetID(PRUint32 aID
)
394 NS_IMETHODIMP
nsSHEntry::GetPageIdentifier(PRUint32
* aResult
)
396 *aResult
= mPageIdentifier
;
400 NS_IMETHODIMP
nsSHEntry::SetPageIdentifier(PRUint32 aPageIdentifier
)
402 mPageIdentifier
= aPageIdentifier
;
406 NS_IMETHODIMP
nsSHEntry::GetDocIdentifier(PRUint64
* aResult
)
408 *aResult
= mDocIdentifier
;
412 NS_IMETHODIMP
nsSHEntry::SetDocIdentifier(PRUint64 aDocIdentifier
)
414 // This ensures that after a session restore, gEntryDocIdentifier is greater
415 // than all SHEntries' docIdentifiers, which ensures that we'll never repeat
417 if (aDocIdentifier
>= gEntryDocIdentifier
)
418 gEntryDocIdentifier
= aDocIdentifier
+ 1;
420 mDocIdentifier
= aDocIdentifier
;
424 NS_IMETHODIMP
nsSHEntry::SetUniqueDocIdentifier()
426 mDocIdentifier
= gEntryDocIdentifier
++;
430 NS_IMETHODIMP
nsSHEntry::GetIsSubFrame(PRBool
* aFlag
)
432 *aFlag
= mIsFrameNavigation
;
436 NS_IMETHODIMP
nsSHEntry::SetIsSubFrame(PRBool aFlag
)
438 mIsFrameNavigation
= aFlag
;
442 NS_IMETHODIMP
nsSHEntry::GetCacheKey(nsISupports
** aResult
)
444 *aResult
= mCacheKey
;
445 NS_IF_ADDREF(*aResult
);
449 NS_IMETHODIMP
nsSHEntry::SetCacheKey(nsISupports
* aCacheKey
)
451 mCacheKey
= aCacheKey
;
455 NS_IMETHODIMP
nsSHEntry::GetSaveLayoutStateFlag(PRBool
* aFlag
)
457 *aFlag
= mSaveLayoutState
;
461 NS_IMETHODIMP
nsSHEntry::SetSaveLayoutStateFlag(PRBool aFlag
)
463 mSaveLayoutState
= aFlag
;
464 if (mLayoutHistoryState
)
465 mLayoutHistoryState
->SetScrollPositionOnly(!aFlag
);
470 NS_IMETHODIMP
nsSHEntry::GetExpirationStatus(PRBool
* aFlag
)
476 NS_IMETHODIMP
nsSHEntry::SetExpirationStatus(PRBool aFlag
)
482 NS_IMETHODIMP
nsSHEntry::GetContentType(nsACString
& aContentType
)
484 aContentType
= mContentType
;
488 NS_IMETHODIMP
nsSHEntry::SetContentType(const nsACString
& aContentType
)
490 mContentType
= aContentType
;
495 nsSHEntry::Create(nsIURI
* aURI
, const nsAString
&aTitle
,
496 nsIInputStream
* aInputStream
,
497 nsILayoutHistoryState
* aLayoutHistoryState
,
498 nsISupports
* aCacheKey
, const nsACString
& aContentType
,
500 PRUint64 aDocShellID
, PRBool aDynamicCreation
)
504 mPostData
= aInputStream
;
505 mCacheKey
= aCacheKey
;
506 mContentType
= aContentType
;
508 mDocShellID
= aDocShellID
;
509 mDynamicallyCreated
= aDynamicCreation
;
511 // Set the LoadType by default to loadHistory during creation
512 mLoadType
= (PRUint32
) nsIDocShellLoadInfo::loadHistory
;
514 // By default all entries are set false for subframe flag.
515 // nsDocShell::CloneAndReplace() which creates entries for
516 // all subframe navigations, sets the flag to true.
517 mIsFrameNavigation
= PR_FALSE
;
519 // By default we save LayoutHistoryState
520 mSaveLayoutState
= PR_TRUE
;
521 mLayoutHistoryState
= aLayoutHistoryState
;
523 //By default the page is not expired
530 nsSHEntry::Clone(nsISHEntry
** aResult
)
532 *aResult
= new nsSHEntry(*this);
534 return NS_ERROR_OUT_OF_MEMORY
;
540 nsSHEntry::GetParent(nsISHEntry
** aResult
)
542 NS_ENSURE_ARG_POINTER(aResult
);
544 NS_IF_ADDREF(*aResult
);
549 nsSHEntry::SetParent(nsISHEntry
* aParent
)
551 /* parent not Addrefed on purpose to avoid cyclic reference
554 * XXX this method should not be scriptable if this is the case!!
561 nsSHEntry::SetWindowState(nsISupports
*aState
)
563 mWindowState
= aState
;
568 nsSHEntry::GetWindowState(nsISupports
**aState
)
570 NS_IF_ADDREF(*aState
= mWindowState
);
575 nsSHEntry::SetViewerBounds(const nsIntRect
&aBounds
)
577 mViewerBounds
= aBounds
;
582 nsSHEntry::GetViewerBounds(nsIntRect
&aBounds
)
584 aBounds
= mViewerBounds
;
589 nsSHEntry::GetOwner(nsISupports
**aOwner
)
591 NS_IF_ADDREF(*aOwner
= mOwner
);
596 nsSHEntry::SetOwner(nsISupports
*aOwner
)
602 //*****************************************************************************
603 // nsSHEntry: nsISHContainer
604 //*****************************************************************************
607 nsSHEntry::GetChildCount(PRInt32
* aCount
)
609 *aCount
= mChildren
.Count();
614 nsSHEntry::AddChild(nsISHEntry
* aChild
, PRInt32 aOffset
)
617 NS_ENSURE_SUCCESS(aChild
->SetParent(this), NS_ERROR_FAILURE
);
621 mChildren
.AppendObject(aChild
);
626 // Bug 52670: Ensure children are added in order.
628 // Later frames in the child list may load faster and get appended
629 // before earlier frames, causing session history to be scrambled.
630 // By growing the list here, they are added to the right position.
632 // Assert that aOffset will not be so high as to grow us a lot.
634 NS_ASSERTION(aOffset
< (mChildren
.Count()+1023), "Large frames array!\n");
637 if (aOffset
< mChildren
.Count()) {
638 nsISHEntry
* oldChild
= mChildren
.ObjectAt(aOffset
);
639 if (aChild
&& oldChild
&& oldChild
!= aChild
) {
640 PRBool dyn
= PR_FALSE
;
641 oldChild
->IsDynamicallyAdded(&dyn
);
642 NS_WARN_IF_FALSE(dyn
, "Adding child where we already have a child? "
643 "This may misbehave");
648 // InsertObjectAt allows only appending one object.
649 // If aOffset is larger than Count(), we must first manually
651 if (aOffset
> mChildren
.Count()) {
652 mChildren
.SetCount(aOffset
);
654 if (!mChildren
.InsertObjectAt(aChild
, aOffset
)) {
655 NS_WARNING("Adding a child failed!");
656 aChild
->SetParent(nsnull
);
657 return NS_ERROR_FAILURE
;
664 nsSHEntry::RemoveChild(nsISHEntry
* aChild
)
666 NS_ENSURE_TRUE(aChild
, NS_ERROR_FAILURE
);
667 PRBool childRemoved
= PR_FALSE
;
668 PRBool dynamic
= PR_FALSE
;
669 aChild
->IsDynamicallyAdded(&dynamic
);
671 childRemoved
= mChildren
.RemoveObject(aChild
);
673 PRInt32 index
= mChildren
.IndexOfObject(aChild
);
675 childRemoved
= mChildren
.ReplaceObjectAt(nsnull
, index
);
679 aChild
->SetParent(nsnull
);
684 nsSHEntry::GetChildAt(PRInt32 aIndex
, nsISHEntry
** aResult
)
686 if (aIndex
>= 0 && aIndex
< mChildren
.Count()) {
687 *aResult
= mChildren
[aIndex
];
688 // yes, mChildren can have holes in it. AddChild's offset parameter makes
690 NS_IF_ADDREF(*aResult
);
698 nsSHEntry::AddChildShell(nsIDocShellTreeItem
*aShell
)
700 NS_ASSERTION(aShell
, "Null child shell added to history entry");
701 mChildShells
.AppendObject(aShell
);
706 nsSHEntry::ChildShellAt(PRInt32 aIndex
, nsIDocShellTreeItem
**aShell
)
708 NS_IF_ADDREF(*aShell
= mChildShells
.SafeObjectAt(aIndex
));
713 nsSHEntry::ClearChildShells()
715 mChildShells
.Clear();
720 nsSHEntry::GetRefreshURIList(nsISupportsArray
**aList
)
722 NS_IF_ADDREF(*aList
= mRefreshURIList
);
727 nsSHEntry::SetRefreshURIList(nsISupportsArray
*aList
)
729 mRefreshURIList
= aList
;
734 nsSHEntry::SyncPresentationState()
736 if (mContentViewer
&& mWindowState
) {
737 // If we have a content viewer and a window state, we should be ok.
741 DropPresentationState();
747 nsSHEntry::DropPresentationState()
749 nsRefPtr
<nsSHEntry
> kungFuDeathGrip
= this;
752 mDocument
->SetBFCacheEntry(nsnull
);
753 mDocument
->RemoveMutationObserver(this);
757 mContentViewer
->ClearHistoryEntry();
759 StopTrackingEntry(this);
760 mContentViewer
= nsnull
;
762 mWindowState
= nsnull
;
763 mViewerBounds
.SetRect(0, 0, 0, 0);
764 mChildShells
.Clear();
765 mRefreshURIList
= nsnull
;
771 // This entry has timed out. If we still have a content viewer, we need to
775 nsCOMPtr
<nsISupports
> container
;
776 mContentViewer
->GetContainer(getter_AddRefs(container
));
777 nsCOMPtr
<nsIDocShellTreeItem
> treeItem
= do_QueryInterface(container
);
780 // We need to find the root DocShell since only that object has an
781 // SHistory and we need the SHistory to evict content viewers
782 nsCOMPtr
<nsIDocShellTreeItem
> root
;
783 treeItem
->GetSameTypeRootTreeItem(getter_AddRefs(root
));
784 nsCOMPtr
<nsIWebNavigation
> webNav
= do_QueryInterface(root
);
785 nsCOMPtr
<nsISHistory
> history
;
786 webNav
->GetSessionHistory(getter_AddRefs(history
));
787 nsCOMPtr
<nsISHistoryInternal
> historyInt
= do_QueryInterface(history
);
790 historyInt
->EvictExpiredContentViewerForEntry(this);
793 //*****************************************************************************
794 // nsSHEntry: nsIMutationObserver
795 //*****************************************************************************
798 nsSHEntry::NodeWillBeDestroyed(const nsINode
* aNode
)
800 NS_NOTREACHED("Document destroyed while we're holding a strong ref to it");
804 nsSHEntry::CharacterDataWillChange(nsIDocument
* aDocument
,
805 nsIContent
* aContent
,
806 CharacterDataChangeInfo
* aInfo
)
811 nsSHEntry::CharacterDataChanged(nsIDocument
* aDocument
,
812 nsIContent
* aContent
,
813 CharacterDataChangeInfo
* aInfo
)
815 RemoveFromBFCacheAsync();
819 nsSHEntry::AttributeWillChange(nsIDocument
* aDocument
,
820 dom::Element
* aContent
,
821 PRInt32 aNameSpaceID
,
828 nsSHEntry::AttributeChanged(nsIDocument
* aDocument
,
829 dom::Element
* aElement
,
830 PRInt32 aNameSpaceID
,
834 RemoveFromBFCacheAsync();
838 nsSHEntry::ContentAppended(nsIDocument
* aDocument
,
839 nsIContent
* aContainer
,
840 nsIContent
* aFirstNewContent
,
841 PRInt32
/* unused */)
843 RemoveFromBFCacheAsync();
847 nsSHEntry::ContentInserted(nsIDocument
* aDocument
,
848 nsIContent
* aContainer
,
850 PRInt32
/* unused */)
852 RemoveFromBFCacheAsync();
856 nsSHEntry::ContentRemoved(nsIDocument
* aDocument
,
857 nsIContent
* aContainer
,
859 PRInt32 aIndexInContainer
,
860 nsIContent
* aPreviousSibling
)
862 RemoveFromBFCacheAsync();
866 nsSHEntry::ParentChainChanged(nsIContent
*aContent
)
870 class DestroyViewerEvent
: public nsRunnable
873 DestroyViewerEvent(nsIContentViewer
* aViewer
, nsIDocument
* aDocument
)
885 nsCOMPtr
<nsIContentViewer
> mViewer
;
886 nsCOMPtr
<nsIDocument
> mDocument
;
890 nsSHEntry::RemoveFromBFCacheSync()
892 NS_ASSERTION(mContentViewer
&& mDocument
,
893 "we're not in the bfcache!");
895 nsCOMPtr
<nsIContentViewer
> viewer
= mContentViewer
;
896 DropPresentationState();
898 // Warning! The call to DropPresentationState could have dropped the last
899 // reference to this nsSHEntry, so no accessing members beyond here.
907 nsSHEntry::RemoveFromBFCacheAsync()
909 NS_ASSERTION(mContentViewer
&& mDocument
,
910 "we're not in the bfcache!");
912 // Release the reference to the contentviewer asynchronously so that the
913 // document doesn't get nuked mid-mutation.
915 nsCOMPtr
<nsIRunnable
> evt
=
916 new DestroyViewerEvent(mContentViewer
, mDocument
);
917 nsresult rv
= NS_DispatchToCurrentThread(evt
);
919 NS_WARNING("failed to dispatch DestroyViewerEvent");
922 // Drop presentation. Also ensures that we don't post more then one
923 // PLEvent. Only do this if we succeeded in posting the event since
924 // otherwise the document could be torn down mid mutation causing crashes.
925 DropPresentationState();
927 // Warning! The call to DropPresentationState could have dropped the last
928 // reference to this nsSHEntry, so no accessing members beyond here.
931 nsDocShellEditorData
*
932 nsSHEntry::ForgetEditorData()
934 return mEditorData
.forget();
938 nsSHEntry::SetEditorData(nsDocShellEditorData
* aData
)
940 NS_ASSERTION(!(aData
&& mEditorData
),
941 "We're going to overwrite an owning ref!");
942 if (mEditorData
!= aData
)
947 nsSHEntry::HasDetachedEditor()
949 return mEditorData
!= nsnull
;
953 nsSHEntry::GetStateData(nsAString
&aStateData
)
955 aStateData
.Assign(mStateData
);
960 nsSHEntry::SetStateData(const nsAString
&aDataStr
)
962 mStateData
.Assign(aDataStr
);
967 nsSHEntry::IsDynamicallyAdded(PRBool
* aAdded
)
969 *aAdded
= mDynamicallyCreated
;
974 nsSHEntry::HasDynamicallyAddedChild(PRBool
* aAdded
)
977 for (PRInt32 i
= 0; i
< mChildren
.Count(); ++i
) {
978 nsISHEntry
* entry
= mChildren
[i
];
980 entry
->IsDynamicallyAdded(aAdded
);
990 nsSHEntry::GetDocshellID(PRUint64
* aID
)
997 nsSHEntry::SetDocshellID(PRUint64 aID
)
1005 nsSHEntry::GetLastTouched(PRUint32
*aLastTouched
)
1007 *aLastTouched
= mLastTouched
;
1012 nsSHEntry::SetLastTouched(PRUint32 aLastTouched
)
1014 mLastTouched
= aLastTouched
;