Fri, 16 Jan 2015 04:50:19 +0100
Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 // Local Includes
7 #include "nsSHEntry.h"
8 #include "nsIDocShellLoadInfo.h"
9 #include "nsIDocShellTreeItem.h"
10 #include "nsDocShellEditorData.h"
11 #include "nsSHEntryShared.h"
12 #include "nsILayoutHistoryState.h"
13 #include "nsIContentViewer.h"
14 #include "nsISupportsArray.h"
15 #include "nsIStructuredCloneContainer.h"
16 #include "nsIInputStream.h"
17 #include "nsIURI.h"
18 #include <algorithm>
20 namespace dom = mozilla::dom;
22 static uint32_t gEntryID = 0;
24 //*****************************************************************************
25 //*** nsSHEntry: Object Management
26 //*****************************************************************************
29 nsSHEntry::nsSHEntry()
30 : mLoadType(0)
31 , mID(gEntryID++)
32 , mScrollPositionX(0)
33 , mScrollPositionY(0)
34 , mParent(nullptr)
35 , mURIWasModified(false)
36 , mIsSrcdocEntry(false)
37 {
38 mShared = new nsSHEntryShared();
39 }
41 nsSHEntry::nsSHEntry(const nsSHEntry &other)
42 : mShared(other.mShared)
43 , mURI(other.mURI)
44 , mReferrerURI(other.mReferrerURI)
45 , mTitle(other.mTitle)
46 , mPostData(other.mPostData)
47 , mLoadType(0) // XXX why not copy?
48 , mID(other.mID)
49 , mScrollPositionX(0) // XXX why not copy?
50 , mScrollPositionY(0) // XXX why not copy?
51 , mParent(other.mParent)
52 , mURIWasModified(other.mURIWasModified)
53 , mStateData(other.mStateData)
54 , mIsSrcdocEntry(other.mIsSrcdocEntry)
55 , mSrcdocData(other.mSrcdocData)
56 , mBaseURI(other.mBaseURI)
57 {
58 }
60 static bool
61 ClearParentPtr(nsISHEntry* aEntry, void* /* aData */)
62 {
63 if (aEntry) {
64 aEntry->SetParent(nullptr);
65 }
66 return true;
67 }
69 nsSHEntry::~nsSHEntry()
70 {
71 // Null out the mParent pointers on all our kids.
72 mChildren.EnumerateForwards(ClearParentPtr, nullptr);
73 }
75 //*****************************************************************************
76 // nsSHEntry: nsISupports
77 //*****************************************************************************
79 NS_IMPL_ISUPPORTS(nsSHEntry, nsISHContainer, nsISHEntry, nsISHEntryInternal)
81 //*****************************************************************************
82 // nsSHEntry: nsISHEntry
83 //*****************************************************************************
85 NS_IMETHODIMP nsSHEntry::SetScrollPosition(int32_t x, int32_t y)
86 {
87 mScrollPositionX = x;
88 mScrollPositionY = y;
89 return NS_OK;
90 }
92 NS_IMETHODIMP nsSHEntry::GetScrollPosition(int32_t *x, int32_t *y)
93 {
94 *x = mScrollPositionX;
95 *y = mScrollPositionY;
96 return NS_OK;
97 }
99 NS_IMETHODIMP nsSHEntry::GetURIWasModified(bool* aOut)
100 {
101 *aOut = mURIWasModified;
102 return NS_OK;
103 }
105 NS_IMETHODIMP nsSHEntry::SetURIWasModified(bool aIn)
106 {
107 mURIWasModified = aIn;
108 return NS_OK;
109 }
111 NS_IMETHODIMP nsSHEntry::GetURI(nsIURI** aURI)
112 {
113 *aURI = mURI;
114 NS_IF_ADDREF(*aURI);
115 return NS_OK;
116 }
118 NS_IMETHODIMP nsSHEntry::SetURI(nsIURI* aURI)
119 {
120 mURI = aURI;
121 return NS_OK;
122 }
124 NS_IMETHODIMP nsSHEntry::GetReferrerURI(nsIURI **aReferrerURI)
125 {
126 *aReferrerURI = mReferrerURI;
127 NS_IF_ADDREF(*aReferrerURI);
128 return NS_OK;
129 }
131 NS_IMETHODIMP nsSHEntry::SetReferrerURI(nsIURI *aReferrerURI)
132 {
133 mReferrerURI = aReferrerURI;
134 return NS_OK;
135 }
137 NS_IMETHODIMP
138 nsSHEntry::SetContentViewer(nsIContentViewer *aViewer)
139 {
140 return mShared->SetContentViewer(aViewer);
141 }
143 NS_IMETHODIMP
144 nsSHEntry::GetContentViewer(nsIContentViewer **aResult)
145 {
146 *aResult = mShared->mContentViewer;
147 NS_IF_ADDREF(*aResult);
148 return NS_OK;
149 }
151 NS_IMETHODIMP
152 nsSHEntry::GetAnyContentViewer(nsISHEntry **aOwnerEntry,
153 nsIContentViewer **aResult)
154 {
155 // Find a content viewer in the root node or any of its children,
156 // assuming that there is only one content viewer total in any one
157 // nsSHEntry tree
158 GetContentViewer(aResult);
159 if (*aResult) {
160 #ifdef DEBUG_PAGE_CACHE
161 printf("Found content viewer\n");
162 #endif
163 *aOwnerEntry = this;
164 NS_ADDREF(*aOwnerEntry);
165 return NS_OK;
166 }
167 // The root SHEntry doesn't have a ContentViewer, so check child nodes
168 for (int32_t i = 0; i < mChildren.Count(); i++) {
169 nsISHEntry* child = mChildren[i];
170 if (child) {
171 #ifdef DEBUG_PAGE_CACHE
172 printf("Evaluating SHEntry child %d\n", i);
173 #endif
174 child->GetAnyContentViewer(aOwnerEntry, aResult);
175 if (*aResult) {
176 return NS_OK;
177 }
178 }
179 }
180 return NS_OK;
181 }
183 NS_IMETHODIMP
184 nsSHEntry::SetSticky(bool aSticky)
185 {
186 mShared->mSticky = aSticky;
187 return NS_OK;
188 }
190 NS_IMETHODIMP
191 nsSHEntry::GetSticky(bool *aSticky)
192 {
193 *aSticky = mShared->mSticky;
194 return NS_OK;
195 }
197 NS_IMETHODIMP nsSHEntry::GetTitle(char16_t** aTitle)
198 {
199 // Check for empty title...
200 if (mTitle.IsEmpty() && mURI) {
201 // Default title is the URL.
202 nsAutoCString spec;
203 if (NS_SUCCEEDED(mURI->GetSpec(spec)))
204 AppendUTF8toUTF16(spec, mTitle);
205 }
207 *aTitle = ToNewUnicode(mTitle);
208 return NS_OK;
209 }
211 NS_IMETHODIMP nsSHEntry::SetTitle(const nsAString &aTitle)
212 {
213 mTitle = aTitle;
214 return NS_OK;
215 }
217 NS_IMETHODIMP nsSHEntry::GetPostData(nsIInputStream** aResult)
218 {
219 *aResult = mPostData;
220 NS_IF_ADDREF(*aResult);
221 return NS_OK;
222 }
224 NS_IMETHODIMP nsSHEntry::SetPostData(nsIInputStream* aPostData)
225 {
226 mPostData = aPostData;
227 return NS_OK;
228 }
230 NS_IMETHODIMP nsSHEntry::GetLayoutHistoryState(nsILayoutHistoryState** aResult)
231 {
232 *aResult = mShared->mLayoutHistoryState;
233 NS_IF_ADDREF(*aResult);
234 return NS_OK;
235 }
237 NS_IMETHODIMP nsSHEntry::SetLayoutHistoryState(nsILayoutHistoryState* aState)
238 {
239 mShared->mLayoutHistoryState = aState;
240 if (mShared->mLayoutHistoryState) {
241 mShared->mLayoutHistoryState->
242 SetScrollPositionOnly(!mShared->mSaveLayoutState);
243 }
245 return NS_OK;
246 }
248 NS_IMETHODIMP nsSHEntry::GetLoadType(uint32_t * aResult)
249 {
250 *aResult = mLoadType;
251 return NS_OK;
252 }
254 NS_IMETHODIMP nsSHEntry::SetLoadType(uint32_t aLoadType)
255 {
256 mLoadType = aLoadType;
257 return NS_OK;
258 }
260 NS_IMETHODIMP nsSHEntry::GetID(uint32_t * aResult)
261 {
262 *aResult = mID;
263 return NS_OK;
264 }
266 NS_IMETHODIMP nsSHEntry::SetID(uint32_t aID)
267 {
268 mID = aID;
269 return NS_OK;
270 }
272 nsSHEntryShared* nsSHEntry::GetSharedState()
273 {
274 return mShared;
275 }
277 NS_IMETHODIMP nsSHEntry::GetIsSubFrame(bool * aFlag)
278 {
279 *aFlag = mShared->mIsFrameNavigation;
280 return NS_OK;
281 }
283 NS_IMETHODIMP nsSHEntry::SetIsSubFrame(bool aFlag)
284 {
285 mShared->mIsFrameNavigation = aFlag;
286 return NS_OK;
287 }
289 NS_IMETHODIMP nsSHEntry::GetCacheKey(nsISupports** aResult)
290 {
291 *aResult = mShared->mCacheKey;
292 NS_IF_ADDREF(*aResult);
293 return NS_OK;
294 }
296 NS_IMETHODIMP nsSHEntry::SetCacheKey(nsISupports* aCacheKey)
297 {
298 mShared->mCacheKey = aCacheKey;
299 return NS_OK;
300 }
302 NS_IMETHODIMP nsSHEntry::GetSaveLayoutStateFlag(bool * aFlag)
303 {
304 *aFlag = mShared->mSaveLayoutState;
305 return NS_OK;
306 }
308 NS_IMETHODIMP nsSHEntry::SetSaveLayoutStateFlag(bool aFlag)
309 {
310 mShared->mSaveLayoutState = aFlag;
311 if (mShared->mLayoutHistoryState) {
312 mShared->mLayoutHistoryState->SetScrollPositionOnly(!aFlag);
313 }
315 return NS_OK;
316 }
318 NS_IMETHODIMP nsSHEntry::GetExpirationStatus(bool * aFlag)
319 {
320 *aFlag = mShared->mExpired;
321 return NS_OK;
322 }
324 NS_IMETHODIMP nsSHEntry::SetExpirationStatus(bool aFlag)
325 {
326 mShared->mExpired = aFlag;
327 return NS_OK;
328 }
330 NS_IMETHODIMP nsSHEntry::GetContentType(nsACString& aContentType)
331 {
332 aContentType = mShared->mContentType;
333 return NS_OK;
334 }
336 NS_IMETHODIMP nsSHEntry::SetContentType(const nsACString& aContentType)
337 {
338 mShared->mContentType = aContentType;
339 return NS_OK;
340 }
342 NS_IMETHODIMP
343 nsSHEntry::Create(nsIURI * aURI, const nsAString &aTitle,
344 nsIInputStream * aInputStream,
345 nsILayoutHistoryState * aLayoutHistoryState,
346 nsISupports * aCacheKey, const nsACString& aContentType,
347 nsISupports* aOwner,
348 uint64_t aDocShellID, bool aDynamicCreation)
349 {
350 mURI = aURI;
351 mTitle = aTitle;
352 mPostData = aInputStream;
354 // Set the LoadType by default to loadHistory during creation
355 mLoadType = (uint32_t) nsIDocShellLoadInfo::loadHistory;
357 mShared->mCacheKey = aCacheKey;
358 mShared->mContentType = aContentType;
359 mShared->mOwner = aOwner;
360 mShared->mDocShellID = aDocShellID;
361 mShared->mDynamicallyCreated = aDynamicCreation;
363 // By default all entries are set false for subframe flag.
364 // nsDocShell::CloneAndReplace() which creates entries for
365 // all subframe navigations, sets the flag to true.
366 mShared->mIsFrameNavigation = false;
368 // By default we save LayoutHistoryState
369 mShared->mSaveLayoutState = true;
370 mShared->mLayoutHistoryState = aLayoutHistoryState;
372 //By default the page is not expired
373 mShared->mExpired = false;
375 mIsSrcdocEntry = false;
376 mSrcdocData = NullString();
378 return NS_OK;
379 }
381 NS_IMETHODIMP
382 nsSHEntry::Clone(nsISHEntry ** aResult)
383 {
384 *aResult = new nsSHEntry(*this);
385 NS_ADDREF(*aResult);
386 return NS_OK;
387 }
389 NS_IMETHODIMP
390 nsSHEntry::GetParent(nsISHEntry ** aResult)
391 {
392 NS_ENSURE_ARG_POINTER(aResult);
393 *aResult = mParent;
394 NS_IF_ADDREF(*aResult);
395 return NS_OK;
396 }
398 NS_IMETHODIMP
399 nsSHEntry::SetParent(nsISHEntry * aParent)
400 {
401 /* parent not Addrefed on purpose to avoid cyclic reference
402 * Null parent is OK
403 *
404 * XXX this method should not be scriptable if this is the case!!
405 */
406 mParent = aParent;
407 return NS_OK;
408 }
410 NS_IMETHODIMP
411 nsSHEntry::SetWindowState(nsISupports *aState)
412 {
413 mShared->mWindowState = aState;
414 return NS_OK;
415 }
417 NS_IMETHODIMP
418 nsSHEntry::GetWindowState(nsISupports **aState)
419 {
420 NS_IF_ADDREF(*aState = mShared->mWindowState);
421 return NS_OK;
422 }
424 NS_IMETHODIMP
425 nsSHEntry::SetViewerBounds(const nsIntRect &aBounds)
426 {
427 mShared->mViewerBounds = aBounds;
428 return NS_OK;
429 }
431 NS_IMETHODIMP
432 nsSHEntry::GetViewerBounds(nsIntRect &aBounds)
433 {
434 aBounds = mShared->mViewerBounds;
435 return NS_OK;
436 }
438 NS_IMETHODIMP
439 nsSHEntry::GetOwner(nsISupports **aOwner)
440 {
441 NS_IF_ADDREF(*aOwner = mShared->mOwner);
442 return NS_OK;
443 }
445 NS_IMETHODIMP
446 nsSHEntry::SetOwner(nsISupports *aOwner)
447 {
448 mShared->mOwner = aOwner;
449 return NS_OK;
450 }
452 NS_IMETHODIMP
453 nsSHEntry::GetBFCacheEntry(nsIBFCacheEntry **aEntry)
454 {
455 NS_ENSURE_ARG_POINTER(aEntry);
456 NS_IF_ADDREF(*aEntry = mShared);
457 return NS_OK;
458 }
460 bool
461 nsSHEntry::HasBFCacheEntry(nsIBFCacheEntry *aEntry)
462 {
463 return static_cast<nsIBFCacheEntry*>(mShared) == aEntry;
464 }
466 NS_IMETHODIMP
467 nsSHEntry::AdoptBFCacheEntry(nsISHEntry *aEntry)
468 {
469 nsCOMPtr<nsISHEntryInternal> shEntry = do_QueryInterface(aEntry);
470 NS_ENSURE_STATE(shEntry);
472 nsSHEntryShared *shared = shEntry->GetSharedState();
473 NS_ENSURE_STATE(shared);
475 mShared = shared;
476 return NS_OK;
477 }
479 NS_IMETHODIMP
480 nsSHEntry::SharesDocumentWith(nsISHEntry *aEntry, bool *aOut)
481 {
482 NS_ENSURE_ARG_POINTER(aOut);
484 nsCOMPtr<nsISHEntryInternal> internal = do_QueryInterface(aEntry);
485 NS_ENSURE_STATE(internal);
487 *aOut = mShared == internal->GetSharedState();
488 return NS_OK;
489 }
491 NS_IMETHODIMP
492 nsSHEntry::AbandonBFCacheEntry()
493 {
494 mShared = nsSHEntryShared::Duplicate(mShared);
495 return NS_OK;
496 }
498 NS_IMETHODIMP
499 nsSHEntry::GetIsSrcdocEntry(bool* aIsSrcdocEntry)
500 {
501 *aIsSrcdocEntry = mIsSrcdocEntry;
502 return NS_OK;
503 }
505 NS_IMETHODIMP
506 nsSHEntry::GetSrcdocData(nsAString &aSrcdocData)
507 {
508 aSrcdocData = mSrcdocData;
509 return NS_OK;
510 }
512 NS_IMETHODIMP
513 nsSHEntry::SetSrcdocData(const nsAString &aSrcdocData)
514 {
515 mSrcdocData = aSrcdocData;
516 mIsSrcdocEntry = true;
517 return NS_OK;
518 }
520 NS_IMETHODIMP
521 nsSHEntry::GetBaseURI(nsIURI **aBaseURI)
522 {
523 *aBaseURI = mBaseURI;
524 NS_IF_ADDREF(*aBaseURI);
525 return NS_OK;
526 }
528 NS_IMETHODIMP
529 nsSHEntry::SetBaseURI(nsIURI *aBaseURI)
530 {
531 mBaseURI = aBaseURI;
532 return NS_OK;
533 }
535 //*****************************************************************************
536 // nsSHEntry: nsISHContainer
537 //*****************************************************************************
539 NS_IMETHODIMP
540 nsSHEntry::GetChildCount(int32_t * aCount)
541 {
542 *aCount = mChildren.Count();
543 return NS_OK;
544 }
546 NS_IMETHODIMP
547 nsSHEntry::AddChild(nsISHEntry * aChild, int32_t aOffset)
548 {
549 if (aChild) {
550 NS_ENSURE_SUCCESS(aChild->SetParent(this), NS_ERROR_FAILURE);
551 }
553 if (aOffset < 0) {
554 mChildren.AppendObject(aChild);
555 return NS_OK;
556 }
558 //
559 // Bug 52670: Ensure children are added in order.
560 //
561 // Later frames in the child list may load faster and get appended
562 // before earlier frames, causing session history to be scrambled.
563 // By growing the list here, they are added to the right position.
564 //
565 // Assert that aOffset will not be so high as to grow us a lot.
566 //
567 NS_ASSERTION(aOffset < (mChildren.Count()+1023), "Large frames array!\n");
569 bool newChildIsDyn = false;
570 if (aChild) {
571 aChild->IsDynamicallyAdded(&newChildIsDyn);
572 }
574 // If the new child is dynamically added, try to add it to aOffset, but if
575 // there are non-dynamically added children, the child must be after those.
576 if (newChildIsDyn) {
577 int32_t lastNonDyn = aOffset - 1;
578 for (int32_t i = aOffset; i < mChildren.Count(); ++i) {
579 nsISHEntry* entry = mChildren[i];
580 if (entry) {
581 bool dyn = false;
582 entry->IsDynamicallyAdded(&dyn);
583 if (dyn) {
584 break;
585 } else {
586 lastNonDyn = i;
587 }
588 }
589 }
590 // InsertObjectAt allows only appending one object.
591 // If aOffset is larger than Count(), we must first manually
592 // set the capacity.
593 if (aOffset > mChildren.Count()) {
594 mChildren.SetCount(aOffset);
595 }
596 if (!mChildren.InsertObjectAt(aChild, lastNonDyn + 1)) {
597 NS_WARNING("Adding a child failed!");
598 aChild->SetParent(nullptr);
599 return NS_ERROR_FAILURE;
600 }
601 } else {
602 // If the new child isn't dynamically added, it should be set to aOffset.
603 // If there are dynamically added children before that, those must be
604 // moved to be after aOffset.
605 if (mChildren.Count() > 0) {
606 int32_t start = std::min(mChildren.Count() - 1, aOffset);
607 int32_t dynEntryIndex = -1;
608 nsISHEntry* dynEntry = nullptr;
609 for (int32_t i = start; i >= 0; --i) {
610 nsISHEntry* entry = mChildren[i];
611 if (entry) {
612 bool dyn = false;
613 entry->IsDynamicallyAdded(&dyn);
614 if (dyn) {
615 dynEntryIndex = i;
616 dynEntry = entry;
617 } else {
618 break;
619 }
620 }
621 }
623 if (dynEntry) {
624 nsCOMArray<nsISHEntry> tmp;
625 tmp.SetCount(aOffset - dynEntryIndex + 1);
626 mChildren.InsertObjectsAt(tmp, dynEntryIndex);
627 NS_ASSERTION(mChildren[aOffset + 1] == dynEntry, "Whaat?");
628 }
629 }
632 // Make sure there isn't anything at aOffset.
633 if (aOffset < mChildren.Count()) {
634 nsISHEntry* oldChild = mChildren[aOffset];
635 if (oldChild && oldChild != aChild) {
636 NS_ERROR("Adding a child where we already have a child? This may misbehave");
637 oldChild->SetParent(nullptr);
638 }
639 }
641 if (!mChildren.ReplaceObjectAt(aChild, aOffset)) {
642 NS_WARNING("Adding a child failed!");
643 aChild->SetParent(nullptr);
644 return NS_ERROR_FAILURE;
645 }
646 }
648 return NS_OK;
649 }
651 NS_IMETHODIMP
652 nsSHEntry::RemoveChild(nsISHEntry * aChild)
653 {
654 NS_ENSURE_TRUE(aChild, NS_ERROR_FAILURE);
655 bool childRemoved = false;
656 bool dynamic = false;
657 aChild->IsDynamicallyAdded(&dynamic);
658 if (dynamic) {
659 childRemoved = mChildren.RemoveObject(aChild);
660 } else {
661 int32_t index = mChildren.IndexOfObject(aChild);
662 if (index >= 0) {
663 childRemoved = mChildren.ReplaceObjectAt(nullptr, index);
664 }
665 }
666 if (childRemoved) {
667 aChild->SetParent(nullptr);
669 // reduce the child count, i.e. remove empty children at the end
670 for (int32_t i = mChildren.Count() - 1; i >= 0 && !mChildren[i]; --i) {
671 if (!mChildren.RemoveObjectAt(i)) {
672 break;
673 }
674 }
675 }
676 return NS_OK;
677 }
679 NS_IMETHODIMP
680 nsSHEntry::GetChildAt(int32_t aIndex, nsISHEntry ** aResult)
681 {
682 if (aIndex >= 0 && aIndex < mChildren.Count()) {
683 *aResult = mChildren[aIndex];
684 // yes, mChildren can have holes in it. AddChild's offset parameter makes
685 // that possible.
686 NS_IF_ADDREF(*aResult);
687 } else {
688 *aResult = nullptr;
689 }
690 return NS_OK;
691 }
693 NS_IMETHODIMP
694 nsSHEntry::AddChildShell(nsIDocShellTreeItem *aShell)
695 {
696 NS_ASSERTION(aShell, "Null child shell added to history entry");
697 mShared->mChildShells.AppendObject(aShell);
698 return NS_OK;
699 }
701 NS_IMETHODIMP
702 nsSHEntry::ChildShellAt(int32_t aIndex, nsIDocShellTreeItem **aShell)
703 {
704 NS_IF_ADDREF(*aShell = mShared->mChildShells.SafeObjectAt(aIndex));
705 return NS_OK;
706 }
708 NS_IMETHODIMP
709 nsSHEntry::ClearChildShells()
710 {
711 mShared->mChildShells.Clear();
712 return NS_OK;
713 }
715 NS_IMETHODIMP
716 nsSHEntry::GetRefreshURIList(nsISupportsArray **aList)
717 {
718 NS_IF_ADDREF(*aList = mShared->mRefreshURIList);
719 return NS_OK;
720 }
722 NS_IMETHODIMP
723 nsSHEntry::SetRefreshURIList(nsISupportsArray *aList)
724 {
725 mShared->mRefreshURIList = aList;
726 return NS_OK;
727 }
729 NS_IMETHODIMP
730 nsSHEntry::SyncPresentationState()
731 {
732 return mShared->SyncPresentationState();
733 }
735 void
736 nsSHEntry::RemoveFromBFCacheSync()
737 {
738 mShared->RemoveFromBFCacheSync();
739 }
741 void
742 nsSHEntry::RemoveFromBFCacheAsync()
743 {
744 mShared->RemoveFromBFCacheAsync();
745 }
747 nsDocShellEditorData*
748 nsSHEntry::ForgetEditorData()
749 {
750 // XXX jlebar Check how this is used.
751 return mShared->mEditorData.forget();
752 }
754 void
755 nsSHEntry::SetEditorData(nsDocShellEditorData* aData)
756 {
757 NS_ASSERTION(!(aData && mShared->mEditorData),
758 "We're going to overwrite an owning ref!");
759 if (mShared->mEditorData != aData) {
760 mShared->mEditorData = aData;
761 }
762 }
764 bool
765 nsSHEntry::HasDetachedEditor()
766 {
767 return mShared->mEditorData != nullptr;
768 }
770 NS_IMETHODIMP
771 nsSHEntry::GetStateData(nsIStructuredCloneContainer **aContainer)
772 {
773 NS_ENSURE_ARG_POINTER(aContainer);
774 NS_IF_ADDREF(*aContainer = mStateData);
775 return NS_OK;
776 }
778 NS_IMETHODIMP
779 nsSHEntry::SetStateData(nsIStructuredCloneContainer *aContainer)
780 {
781 mStateData = aContainer;
782 return NS_OK;
783 }
785 NS_IMETHODIMP
786 nsSHEntry::IsDynamicallyAdded(bool* aAdded)
787 {
788 *aAdded = mShared->mDynamicallyCreated;
789 return NS_OK;
790 }
792 NS_IMETHODIMP
793 nsSHEntry::HasDynamicallyAddedChild(bool* aAdded)
794 {
795 *aAdded = false;
796 for (int32_t i = 0; i < mChildren.Count(); ++i) {
797 nsISHEntry* entry = mChildren[i];
798 if (entry) {
799 entry->IsDynamicallyAdded(aAdded);
800 if (*aAdded) {
801 break;
802 }
803 }
804 }
805 return NS_OK;
806 }
808 NS_IMETHODIMP
809 nsSHEntry::GetDocshellID(uint64_t* aID)
810 {
811 *aID = mShared->mDocShellID;
812 return NS_OK;
813 }
815 NS_IMETHODIMP
816 nsSHEntry::SetDocshellID(uint64_t aID)
817 {
818 mShared->mDocShellID = aID;
819 return NS_OK;
820 }
823 NS_IMETHODIMP
824 nsSHEntry::GetLastTouched(uint32_t *aLastTouched)
825 {
826 *aLastTouched = mShared->mLastTouched;
827 return NS_OK;
828 }
830 NS_IMETHODIMP
831 nsSHEntry::SetLastTouched(uint32_t aLastTouched)
832 {
833 mShared->mLastTouched = aLastTouched;
834 return NS_OK;
835 }