1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
11 #include "nsDocShell.h"
12 #include "nsDocShellEditorData.h"
13 #include "nsDocShellLoadState.h"
14 #include "nsDocShellLoadTypes.h"
15 #include "nsIContentSecurityPolicy.h"
16 #include "nsIDocShellTreeItem.h"
17 #include "nsIDocumentViewer.h"
18 #include "nsIInputStream.h"
19 #include "nsILayoutHistoryState.h"
20 #include "nsIMutableArray.h"
21 #include "nsIStructuredCloneContainer.h"
23 #include "nsSHEntryShared.h"
24 #include "nsSHistory.h"
26 #include "mozilla/Logging.h"
27 #include "nsIReferrerInfo.h"
29 extern mozilla::LazyLogModule gPageCacheLog
;
31 static uint32_t gEntryID
= 0;
33 nsSHEntry::nsSHEntry()
34 : mShared(new nsSHEntryShared()),
36 mID(++gEntryID
), // SessionStore has special handling for 0 values.
40 mURIWasModified(false),
41 mIsSrcdocEntry(false),
42 mScrollRestorationIsManual(false),
43 mLoadedInThisProcess(false),
45 mHasUserInteraction(false),
46 mHasUserActivation(false) {}
48 nsSHEntry::nsSHEntry(const nsSHEntry
& aOther
)
49 : mShared(aOther
.mShared
),
51 mOriginalURI(aOther
.mOriginalURI
),
52 mResultPrincipalURI(aOther
.mResultPrincipalURI
),
53 mUnstrippedURI(aOther
.mUnstrippedURI
),
54 mReferrerInfo(aOther
.mReferrerInfo
),
55 mTitle(aOther
.mTitle
),
56 mPostData(aOther
.mPostData
),
57 mLoadType(0), // XXX why not copy?
59 mScrollPositionX(0), // XXX why not copy?
60 mScrollPositionY(0), // XXX why not copy?
61 mParent(aOther
.mParent
),
62 mStateData(aOther
.mStateData
),
63 mSrcdocData(aOther
.mSrcdocData
),
64 mBaseURI(aOther
.mBaseURI
),
65 mLoadReplace(aOther
.mLoadReplace
),
66 mURIWasModified(aOther
.mURIWasModified
),
67 mIsSrcdocEntry(aOther
.mIsSrcdocEntry
),
68 mScrollRestorationIsManual(false),
69 mLoadedInThisProcess(aOther
.mLoadedInThisProcess
),
70 mPersist(aOther
.mPersist
),
71 mHasUserInteraction(false),
72 mHasUserActivation(aOther
.mHasUserActivation
) {}
74 nsSHEntry::~nsSHEntry() {
75 // Null out the mParent pointers on all our kids.
76 for (nsISHEntry
* entry
: mChildren
) {
78 entry
->SetParent(nullptr);
83 NS_IMPL_ISUPPORTS(nsSHEntry
, nsISHEntry
, nsISupportsWeakReference
)
86 nsSHEntry::SetScrollPosition(int32_t aX
, int32_t aY
) {
87 mScrollPositionX
= aX
;
88 mScrollPositionY
= aY
;
93 nsSHEntry::GetScrollPosition(int32_t* aX
, int32_t* aY
) {
94 *aX
= mScrollPositionX
;
95 *aY
= mScrollPositionY
;
100 nsSHEntry::GetURIWasModified(bool* aOut
) {
101 *aOut
= mURIWasModified
;
106 nsSHEntry::SetURIWasModified(bool aIn
) {
107 mURIWasModified
= aIn
;
112 nsSHEntry::GetURI(nsIURI
** aURI
) {
119 nsSHEntry::SetURI(nsIURI
* aURI
) {
125 nsSHEntry::GetOriginalURI(nsIURI
** aOriginalURI
) {
126 *aOriginalURI
= mOriginalURI
;
127 NS_IF_ADDREF(*aOriginalURI
);
132 nsSHEntry::SetOriginalURI(nsIURI
* aOriginalURI
) {
133 mOriginalURI
= aOriginalURI
;
138 nsSHEntry::GetResultPrincipalURI(nsIURI
** aResultPrincipalURI
) {
139 *aResultPrincipalURI
= mResultPrincipalURI
;
140 NS_IF_ADDREF(*aResultPrincipalURI
);
145 nsSHEntry::SetResultPrincipalURI(nsIURI
* aResultPrincipalURI
) {
146 mResultPrincipalURI
= aResultPrincipalURI
;
151 nsSHEntry::GetUnstrippedURI(nsIURI
** aUnstrippedURI
) {
152 *aUnstrippedURI
= mUnstrippedURI
;
153 NS_IF_ADDREF(*aUnstrippedURI
);
158 nsSHEntry::SetUnstrippedURI(nsIURI
* aUnstrippedURI
) {
159 mUnstrippedURI
= aUnstrippedURI
;
164 nsSHEntry::GetLoadReplace(bool* aLoadReplace
) {
165 *aLoadReplace
= mLoadReplace
;
170 nsSHEntry::SetLoadReplace(bool aLoadReplace
) {
171 mLoadReplace
= aLoadReplace
;
176 nsSHEntry::GetReferrerInfo(nsIReferrerInfo
** aReferrerInfo
) {
177 *aReferrerInfo
= mReferrerInfo
;
178 NS_IF_ADDREF(*aReferrerInfo
);
183 nsSHEntry::SetReferrerInfo(nsIReferrerInfo
* aReferrerInfo
) {
184 mReferrerInfo
= aReferrerInfo
;
189 nsSHEntry::SetSticky(bool aSticky
) {
190 mShared
->mSticky
= aSticky
;
195 nsSHEntry::GetSticky(bool* aSticky
) {
196 *aSticky
= mShared
->mSticky
;
201 nsSHEntry::GetTitle(nsAString
& aTitle
) {
202 // Check for empty title...
203 if (mTitle
.IsEmpty() && mURI
) {
204 // Default title is the URL.
206 if (NS_SUCCEEDED(mURI
->GetSpec(spec
))) {
207 AppendUTF8toUTF16(spec
, mTitle
);
216 nsSHEntry::SetTitle(const nsAString
& aTitle
) {
222 nsSHEntry::GetName(nsAString
& aName
) {
228 nsSHEntry::SetName(const nsAString
& aName
) {
234 nsSHEntry::GetPostData(nsIInputStream
** aResult
) {
235 *aResult
= mPostData
;
236 NS_IF_ADDREF(*aResult
);
241 nsSHEntry::SetPostData(nsIInputStream
* aPostData
) {
242 mPostData
= aPostData
;
247 nsSHEntry::GetHasPostData(bool* aResult
) {
248 *aResult
= !!mPostData
;
253 nsSHEntry::GetLayoutHistoryState(nsILayoutHistoryState
** aResult
) {
254 *aResult
= mShared
->mLayoutHistoryState
;
255 NS_IF_ADDREF(*aResult
);
260 nsSHEntry::SetLayoutHistoryState(nsILayoutHistoryState
* aState
) {
261 mShared
->mLayoutHistoryState
= aState
;
262 if (mShared
->mLayoutHistoryState
) {
263 mShared
->mLayoutHistoryState
->SetScrollPositionOnly(
264 !mShared
->mSaveLayoutState
);
271 nsSHEntry::InitLayoutHistoryState(nsILayoutHistoryState
** aState
) {
272 if (!mShared
->mLayoutHistoryState
) {
273 nsCOMPtr
<nsILayoutHistoryState
> historyState
;
274 historyState
= NS_NewLayoutHistoryState();
275 SetLayoutHistoryState(historyState
);
278 nsCOMPtr
<nsILayoutHistoryState
> state
= GetLayoutHistoryState();
279 state
.forget(aState
);
284 nsSHEntry::GetLoadType(uint32_t* aResult
) {
285 *aResult
= mLoadType
;
290 nsSHEntry::SetLoadType(uint32_t aLoadType
) {
291 mLoadType
= aLoadType
;
296 nsSHEntry::GetID(uint32_t* aResult
) {
302 nsSHEntry::SetID(uint32_t aID
) {
308 nsSHEntry::GetIsSubFrame(bool* aFlag
) {
309 *aFlag
= mShared
->mIsFrameNavigation
;
314 nsSHEntry::SetIsSubFrame(bool aFlag
) {
315 mShared
->mIsFrameNavigation
= aFlag
;
320 nsSHEntry::GetHasUserInteraction(bool* aFlag
) {
321 // The back button and menulist deal with root/top-level
322 // session history entries, thus we annotate only the root entry.
324 *aFlag
= mHasUserInteraction
;
326 nsCOMPtr
<nsISHEntry
> root
= nsSHistory::GetRootSHEntry(this);
327 root
->GetHasUserInteraction(aFlag
);
333 nsSHEntry::SetHasUserInteraction(bool aFlag
) {
334 // The back button and menulist deal with root/top-level
335 // session history entries, thus we annotate only the root entry.
337 mHasUserInteraction
= aFlag
;
339 nsCOMPtr
<nsISHEntry
> root
= nsSHistory::GetRootSHEntry(this);
340 root
->SetHasUserInteraction(aFlag
);
346 nsSHEntry::GetHasUserActivation(bool* aFlag
) {
347 *aFlag
= mHasUserActivation
;
352 nsSHEntry::SetHasUserActivation(bool aFlag
) {
353 mHasUserActivation
= aFlag
;
358 nsSHEntry::GetCacheKey(uint32_t* aResult
) {
359 *aResult
= mShared
->mCacheKey
;
364 nsSHEntry::SetCacheKey(uint32_t aCacheKey
) {
365 mShared
->mCacheKey
= aCacheKey
;
370 nsSHEntry::GetContentType(nsACString
& aContentType
) {
371 aContentType
= mShared
->mContentType
;
376 nsSHEntry::SetContentType(const nsACString
& aContentType
) {
377 mShared
->mContentType
= aContentType
;
383 nsIURI
* aURI
, const nsAString
& aTitle
, nsIInputStream
* aInputStream
,
384 uint32_t aCacheKey
, const nsACString
& aContentType
,
385 nsIPrincipal
* aTriggeringPrincipal
, nsIPrincipal
* aPrincipalToInherit
,
386 nsIPrincipal
* aPartitionedPrincipalToInherit
,
387 nsIContentSecurityPolicy
* aCsp
, const nsID
& aDocShellID
,
388 bool aDynamicCreation
, nsIURI
* aOriginalURI
, nsIURI
* aResultPrincipalURI
,
389 nsIURI
* aUnstrippedURI
, bool aLoadReplace
, nsIReferrerInfo
* aReferrerInfo
,
390 const nsAString
& aSrcdocData
, bool aSrcdocEntry
, nsIURI
* aBaseURI
,
391 bool aSaveLayoutState
, bool aExpired
, bool aUserActivation
) {
393 aTriggeringPrincipal
,
394 "need a valid triggeringPrincipal to create a session history entry");
398 mPostData
= aInputStream
;
400 // Set the LoadType by default to loadHistory during creation
401 mLoadType
= LOAD_HISTORY
;
403 mShared
->mCacheKey
= aCacheKey
;
404 mShared
->mContentType
= aContentType
;
405 mShared
->mTriggeringPrincipal
= aTriggeringPrincipal
;
406 mShared
->mPrincipalToInherit
= aPrincipalToInherit
;
407 mShared
->mPartitionedPrincipalToInherit
= aPartitionedPrincipalToInherit
;
408 mShared
->mCsp
= aCsp
;
409 mShared
->mDocShellID
= aDocShellID
;
410 mShared
->mDynamicallyCreated
= aDynamicCreation
;
412 // By default all entries are set false for subframe flag.
413 // nsDocShell::CloneAndReplace() which creates entries for
414 // all subframe navigations, sets the flag to true.
415 mShared
->mIsFrameNavigation
= false;
417 mHasUserInteraction
= false;
419 mShared
->mExpired
= aExpired
;
421 mIsSrcdocEntry
= aSrcdocEntry
;
422 mSrcdocData
= aSrcdocData
;
426 mLoadedInThisProcess
= true;
428 mOriginalURI
= aOriginalURI
;
429 mResultPrincipalURI
= aResultPrincipalURI
;
430 mUnstrippedURI
= aUnstrippedURI
;
431 mLoadReplace
= aLoadReplace
;
432 mReferrerInfo
= aReferrerInfo
;
434 mHasUserActivation
= aUserActivation
;
436 mShared
->mLayoutHistoryState
= nullptr;
438 mShared
->mSaveLayoutState
= aSaveLayoutState
;
444 nsSHEntry::GetParent(nsISHEntry
** aResult
) {
445 nsCOMPtr
<nsISHEntry
> parent
= do_QueryReferent(mParent
);
446 parent
.forget(aResult
);
451 nsSHEntry::SetParent(nsISHEntry
* aParent
) {
452 mParent
= do_GetWeakReference(aParent
);
457 nsSHEntry::SetViewerBounds(const nsIntRect
& aBounds
) {
458 mShared
->mViewerBounds
= aBounds
;
462 nsSHEntry::GetViewerBounds(nsIntRect
& aBounds
) {
463 aBounds
= mShared
->mViewerBounds
;
467 nsSHEntry::GetTriggeringPrincipal(nsIPrincipal
** aTriggeringPrincipal
) {
468 NS_IF_ADDREF(*aTriggeringPrincipal
= mShared
->mTriggeringPrincipal
);
473 nsSHEntry::SetTriggeringPrincipal(nsIPrincipal
* aTriggeringPrincipal
) {
474 mShared
->mTriggeringPrincipal
= aTriggeringPrincipal
;
479 nsSHEntry::GetPrincipalToInherit(nsIPrincipal
** aPrincipalToInherit
) {
480 NS_IF_ADDREF(*aPrincipalToInherit
= mShared
->mPrincipalToInherit
);
485 nsSHEntry::SetPrincipalToInherit(nsIPrincipal
* aPrincipalToInherit
) {
486 mShared
->mPrincipalToInherit
= aPrincipalToInherit
;
491 nsSHEntry::GetPartitionedPrincipalToInherit(
492 nsIPrincipal
** aPartitionedPrincipalToInherit
) {
493 NS_IF_ADDREF(*aPartitionedPrincipalToInherit
=
494 mShared
->mPartitionedPrincipalToInherit
);
499 nsSHEntry::SetPartitionedPrincipalToInherit(
500 nsIPrincipal
* aPartitionedPrincipalToInherit
) {
501 mShared
->mPartitionedPrincipalToInherit
= aPartitionedPrincipalToInherit
;
506 nsSHEntry::GetCsp(nsIContentSecurityPolicy
** aCsp
) {
507 NS_IF_ADDREF(*aCsp
= mShared
->mCsp
);
512 nsSHEntry::SetCsp(nsIContentSecurityPolicy
* aCsp
) {
513 mShared
->mCsp
= aCsp
;
518 nsSHEntry::AdoptBFCacheEntry(nsISHEntry
* aEntry
) {
519 nsSHEntryShared
* shared
= static_cast<nsSHEntry
*>(aEntry
)->mShared
;
520 NS_ENSURE_STATE(shared
);
527 nsSHEntry::SharesDocumentWith(nsISHEntry
* aEntry
, bool* aOut
) {
528 NS_ENSURE_ARG_POINTER(aOut
);
530 *aOut
= mShared
== static_cast<nsSHEntry
*>(aEntry
)->mShared
;
535 nsSHEntry::GetIsSrcdocEntry(bool* aIsSrcdocEntry
) {
536 *aIsSrcdocEntry
= mIsSrcdocEntry
;
541 nsSHEntry::GetSrcdocData(nsAString
& aSrcdocData
) {
542 aSrcdocData
= mSrcdocData
;
547 nsSHEntry::SetSrcdocData(const nsAString
& aSrcdocData
) {
548 mSrcdocData
= aSrcdocData
;
549 mIsSrcdocEntry
= true;
554 nsSHEntry::GetBaseURI(nsIURI
** aBaseURI
) {
555 *aBaseURI
= mBaseURI
;
556 NS_IF_ADDREF(*aBaseURI
);
561 nsSHEntry::SetBaseURI(nsIURI
* aBaseURI
) {
567 nsSHEntry::GetScrollRestorationIsManual(bool* aIsManual
) {
568 *aIsManual
= mScrollRestorationIsManual
;
573 nsSHEntry::SetScrollRestorationIsManual(bool aIsManual
) {
574 mScrollRestorationIsManual
= aIsManual
;
579 nsSHEntry::GetLoadedInThisProcess(bool* aLoadedInThisProcess
) {
580 *aLoadedInThisProcess
= mLoadedInThisProcess
;
585 nsSHEntry::GetChildCount(int32_t* aCount
) {
586 *aCount
= mChildren
.Count();
591 nsSHEntry::AddChild(nsISHEntry
* aChild
, int32_t aOffset
,
592 bool aUseRemoteSubframes
) {
594 NS_ENSURE_SUCCESS(aChild
->SetParent(this), NS_ERROR_FAILURE
);
598 mChildren
.AppendObject(aChild
);
603 // Bug 52670: Ensure children are added in order.
605 // Later frames in the child list may load faster and get appended
606 // before earlier frames, causing session history to be scrambled.
607 // By growing the list here, they are added to the right position.
609 // Assert that aOffset will not be so high as to grow us a lot.
611 NS_ASSERTION(aOffset
< (mChildren
.Count() + 1023), "Large frames array!\n");
613 bool newChildIsDyn
= aChild
? aChild
->IsDynamicallyAdded() : false;
615 // If the new child is dynamically added, try to add it to aOffset, but if
616 // there are non-dynamically added children, the child must be after those.
618 int32_t lastNonDyn
= aOffset
- 1;
619 for (int32_t i
= aOffset
; i
< mChildren
.Count(); ++i
) {
620 nsISHEntry
* entry
= mChildren
[i
];
622 if (entry
->IsDynamicallyAdded()) {
629 // InsertObjectAt allows only appending one object.
630 // If aOffset is larger than Count(), we must first manually
632 if (aOffset
> mChildren
.Count()) {
633 mChildren
.SetCount(aOffset
);
635 if (!mChildren
.InsertObjectAt(aChild
, lastNonDyn
+ 1)) {
636 NS_WARNING("Adding a child failed!");
637 aChild
->SetParent(nullptr);
638 return NS_ERROR_FAILURE
;
641 // If the new child isn't dynamically added, it should be set to aOffset.
642 // If there are dynamically added children before that, those must be
643 // moved to be after aOffset.
644 if (mChildren
.Count() > 0) {
645 int32_t start
= std::min(mChildren
.Count() - 1, aOffset
);
646 int32_t dynEntryIndex
= -1;
647 nsISHEntry
* dynEntry
= nullptr;
648 for (int32_t i
= start
; i
>= 0; --i
) {
649 nsISHEntry
* entry
= mChildren
[i
];
651 if (entry
->IsDynamicallyAdded()) {
661 nsCOMArray
<nsISHEntry
> tmp
;
662 tmp
.SetCount(aOffset
- dynEntryIndex
+ 1);
663 mChildren
.InsertObjectsAt(tmp
, dynEntryIndex
);
664 NS_ASSERTION(mChildren
[aOffset
+ 1] == dynEntry
, "Whaat?");
668 // Make sure there isn't anything at aOffset.
669 if (aOffset
< mChildren
.Count()) {
670 nsISHEntry
* oldChild
= mChildren
[aOffset
];
671 if (oldChild
&& oldChild
!= aChild
) {
672 // Under Fission, this can happen when a network-created iframe starts
673 // out in-process, moves out-of-process, and then switches back. At that
674 // point, we'll create a new network-created DocShell at the same index
675 // where we already have an entry for the original network-created
678 // This should ideally stop being an issue once the Fission-aware
679 // session history rewrite is complete.
682 "Adding a child where we already have a child? This may misbehave");
683 oldChild
->SetParent(nullptr);
687 mChildren
.ReplaceObjectAt(aChild
, aOffset
);
694 nsSHEntry::RemoveChild(nsISHEntry
* aChild
) {
695 NS_ENSURE_TRUE(aChild
, NS_ERROR_FAILURE
);
696 bool childRemoved
= false;
697 if (aChild
->IsDynamicallyAdded()) {
698 childRemoved
= mChildren
.RemoveObject(aChild
);
700 int32_t index
= mChildren
.IndexOfObject(aChild
);
702 // Other alive non-dynamic child docshells still keep mChildOffset,
703 // so we don't want to change the indices here.
704 mChildren
.ReplaceObjectAt(nullptr, index
);
709 aChild
->SetParent(nullptr);
711 // reduce the child count, i.e. remove empty children at the end
712 for (int32_t i
= mChildren
.Count() - 1; i
>= 0 && !mChildren
[i
]; --i
) {
713 if (!mChildren
.RemoveObjectAt(i
)) {
722 nsSHEntry::GetChildAt(int32_t aIndex
, nsISHEntry
** aResult
) {
723 if (aIndex
>= 0 && aIndex
< mChildren
.Count()) {
724 *aResult
= mChildren
[aIndex
];
725 // yes, mChildren can have holes in it. AddChild's offset parameter makes
727 NS_IF_ADDREF(*aResult
);
735 nsSHEntry::GetChildSHEntryIfHasNoDynamicallyAddedChild(int32_t aChildOffset
,
736 nsISHEntry
** aChild
) {
739 bool dynamicallyAddedChild
= false;
740 HasDynamicallyAddedChild(&dynamicallyAddedChild
);
741 if (dynamicallyAddedChild
) {
745 // If the user did a shift-reload on this frameset page,
746 // we don't want to load the subframes from history.
747 if (IsForceReloadType(mLoadType
) || mLoadType
== LOAD_REFRESH
) {
751 /* Before looking for the subframe's url, check
752 * the expiration status of the parent. If the parent
753 * has expired from cache, then subframes will not be
754 * loaded from history in certain situations.
755 * If the user pressed reload and the parent frame has expired
756 * from cache, we do not want to load the child frame from history.
758 if (mShared
->mExpired
&& (mLoadType
== LOAD_RELOAD_NORMAL
)) {
759 // The parent has expired. Return null.
763 // Get the child subframe from session history.
764 GetChildAt(aChildOffset
, aChild
);
766 // Set the parent's Load Type on the child
767 (*aChild
)->SetLoadType(mLoadType
);
772 nsSHEntry::ReplaceChild(nsISHEntry
* aNewEntry
) {
773 NS_ENSURE_STATE(aNewEntry
);
776 aNewEntry
->GetDocshellID(docshellID
);
778 for (int32_t i
= 0; i
< mChildren
.Count(); ++i
) {
780 nsID childDocshellID
;
781 nsresult rv
= mChildren
[i
]->GetDocshellID(childDocshellID
);
782 NS_ENSURE_SUCCESS(rv
, rv
);
783 if (docshellID
== childDocshellID
) {
784 mChildren
[i
]->SetParent(nullptr);
785 mChildren
.ReplaceObjectAt(aNewEntry
, i
);
786 return aNewEntry
->SetParent(this);
790 return NS_ERROR_FAILURE
;
793 NS_IMETHODIMP_(void) nsSHEntry::ClearEntry() {
794 int32_t childCount
= GetChildCount();
795 // Remove all children of this entry
796 for (int32_t i
= childCount
- 1; i
>= 0; i
--) {
797 nsCOMPtr
<nsISHEntry
> child
;
798 GetChildAt(i
, getter_AddRefs(child
));
801 AbandonBFCacheEntry();
805 nsSHEntry::GetStateData(nsIStructuredCloneContainer
** aContainer
) {
806 NS_IF_ADDREF(*aContainer
= mStateData
);
811 nsSHEntry::SetStateData(nsIStructuredCloneContainer
* aContainer
) {
812 mStateData
= aContainer
;
817 nsSHEntry::IsDynamicallyAdded() { return mShared
->mDynamicallyCreated
; }
820 nsSHEntry::HasDynamicallyAddedChild(bool* aAdded
) {
822 for (int32_t i
= 0; i
< mChildren
.Count(); ++i
) {
823 nsISHEntry
* entry
= mChildren
[i
];
825 *aAdded
= entry
->IsDynamicallyAdded();
835 nsSHEntry::GetDocshellID(nsID
& aID
) {
836 aID
= mShared
->mDocShellID
;
841 nsSHEntry::SetDocshellID(const nsID
& aID
) {
842 mShared
->mDocShellID
= aID
;
847 nsSHEntry::GetLastTouched(uint32_t* aLastTouched
) {
848 *aLastTouched
= mShared
->mLastTouched
;
853 nsSHEntry::SetLastTouched(uint32_t aLastTouched
) {
854 mShared
->mLastTouched
= aLastTouched
;
859 nsSHEntry::GetShistory(nsISHistory
** aSHistory
) {
860 nsCOMPtr
<nsISHistory
> shistory(do_QueryReferent(mShared
->mSHistory
));
861 shistory
.forget(aSHistory
);
866 nsSHEntry::SetShistory(nsISHistory
* aSHistory
) {
867 nsWeakPtr shistory
= do_GetWeakReference(aSHistory
);
868 // mSHistory can not be changed once it's set
869 MOZ_ASSERT(!mShared
->mSHistory
|| (mShared
->mSHistory
== shistory
));
870 mShared
->mSHistory
= shistory
;
875 nsSHEntry::SetLoadTypeAsHistory() {
876 // Set the LoadType by default to loadHistory during creation
877 mLoadType
= LOAD_HISTORY
;
882 nsSHEntry::GetPersist(bool* aPersist
) {
883 *aPersist
= mPersist
;
888 nsSHEntry::SetPersist(bool aPersist
) {
894 nsSHEntry::CreateLoadInfo(nsDocShellLoadState
** aLoadState
) {
895 nsCOMPtr
<nsIURI
> uri
= GetURI();
896 RefPtr
<nsDocShellLoadState
> loadState(new nsDocShellLoadState(uri
));
898 nsCOMPtr
<nsIURI
> originalURI
= GetOriginalURI();
899 loadState
->SetOriginalURI(originalURI
);
901 mozilla::Maybe
<nsCOMPtr
<nsIURI
>> emplacedResultPrincipalURI
;
902 nsCOMPtr
<nsIURI
> resultPrincipalURI
= GetResultPrincipalURI();
903 emplacedResultPrincipalURI
.emplace(std::move(resultPrincipalURI
));
904 loadState
->SetMaybeResultPrincipalURI(emplacedResultPrincipalURI
);
906 nsCOMPtr
<nsIURI
> unstrippedURI
= GetUnstrippedURI();
907 loadState
->SetUnstrippedURI(unstrippedURI
);
909 loadState
->SetLoadReplace(GetLoadReplace());
910 nsCOMPtr
<nsIInputStream
> postData
= GetPostData();
911 loadState
->SetPostDataStream(postData
);
913 nsAutoCString contentType
;
914 GetContentType(contentType
);
915 loadState
->SetTypeHint(contentType
);
917 nsCOMPtr
<nsIPrincipal
> triggeringPrincipal
= GetTriggeringPrincipal();
918 loadState
->SetTriggeringPrincipal(triggeringPrincipal
);
919 nsCOMPtr
<nsIPrincipal
> principalToInherit
= GetPrincipalToInherit();
920 loadState
->SetPrincipalToInherit(principalToInherit
);
921 nsCOMPtr
<nsIPrincipal
> partitionedPrincipalToInherit
=
922 GetPartitionedPrincipalToInherit();
923 loadState
->SetPartitionedPrincipalToInherit(partitionedPrincipalToInherit
);
924 nsCOMPtr
<nsIContentSecurityPolicy
> csp
= GetCsp();
925 loadState
->SetCsp(csp
);
926 nsCOMPtr
<nsIReferrerInfo
> referrerInfo
= GetReferrerInfo();
927 loadState
->SetReferrerInfo(referrerInfo
);
929 // Do not inherit principal from document (security-critical!);
930 uint32_t flags
= nsDocShell::InternalLoad::INTERNAL_LOAD_FLAGS_NONE
;
932 // Passing nullptr as aSourceDocShell gives the same behaviour as before
933 // aSourceDocShell was introduced. According to spec we should be passing
934 // the source browsing context that was used when the history entry was
935 // first created. bug 947716 has been created to address this issue.
937 nsCOMPtr
<nsIURI
> baseURI
;
938 if (GetIsSrcdocEntry()) {
939 GetSrcdocData(srcdoc
);
940 baseURI
= GetBaseURI();
941 flags
|= nsDocShell::InternalLoad::INTERNAL_LOAD_FLAGS_IS_SRCDOC
;
943 srcdoc
= VoidString();
945 loadState
->SetSrcdocData(srcdoc
);
946 loadState
->SetBaseURI(baseURI
);
947 loadState
->SetInternalLoadFlags(flags
);
949 loadState
->SetFirstParty(true);
951 const bool hasUserActivation
= GetHasUserActivation();
952 loadState
->SetHasValidUserGestureActivation(hasUserActivation
);
953 loadState
->SetTextDirectiveUserActivation(hasUserActivation
);
955 loadState
->SetSHEntry(this);
957 // When we create a load state from the history entry we already know if
958 // https-first was able to upgrade the request from http to https. There is no
959 // point in re-retrying to upgrade.
960 loadState
->SetIsExemptFromHTTPSFirstMode(true);
962 loadState
.forget(aLoadState
);
967 nsSHEntry::SyncTreesForSubframeNavigation(
968 nsISHEntry
* aEntry
, mozilla::dom::BrowsingContext
* aTopBC
,
969 mozilla::dom::BrowsingContext
* aIgnoreBC
) {
970 // XXX Keep this in sync with
971 // SessionHistoryEntry::SyncTreesForSubframeNavigation
973 // We need to sync up the browsing context and session history trees for
974 // subframe navigation. If the load was in a subframe, we forward up to
975 // the top browsing context, which will then recursively sync up all browsing
976 // contexts to their corresponding entries in the new session history tree. If
977 // we don't do this, then we can cache a content viewer on the wrong cloned
978 // entry, and subsequently restore it at the wrong time.
979 nsCOMPtr
<nsISHEntry
> newRootEntry
= nsSHistory::GetRootSHEntry(aEntry
);
981 // newRootEntry is now the new root entry.
982 // Find the old root entry as well.
984 // Need a strong ref. on |oldRootEntry| so it isn't destroyed when
985 // SetChildHistoryEntry() does SwapHistoryEntries() (bug 304639).
986 nsCOMPtr
<nsISHEntry
> oldRootEntry
= nsSHistory::GetRootSHEntry(this);
989 nsSHistory::SwapEntriesData data
= {aIgnoreBC
, newRootEntry
, nullptr};
990 nsSHistory::SetChildHistoryEntry(oldRootEntry
, aTopBC
, 0, &data
);
995 void nsSHEntry::EvictDocumentViewer() {
996 nsCOMPtr
<nsIDocumentViewer
> viewer
= GetDocumentViewer();
998 mShared
->NotifyListenersDocumentViewerEvicted();
999 // Drop the presentation state before destroying the viewer, so that
1000 // document teardown is able to correctly persist the state.
1001 SetDocumentViewer(nullptr);
1002 SyncPresentationState();
1008 nsSHEntry::SetDocumentViewer(nsIDocumentViewer
* aViewer
) {
1009 return GetState()->SetDocumentViewer(aViewer
);
1013 nsSHEntry::GetDocumentViewer(nsIDocumentViewer
** aResult
) {
1014 *aResult
= GetState()->mDocumentViewer
;
1015 NS_IF_ADDREF(*aResult
);
1020 nsSHEntry::GetIsInBFCache(bool* aResult
) {
1021 *aResult
= !!GetState()->mDocumentViewer
;
1026 nsSHEntry::Clone(nsISHEntry
** aResult
) {
1027 nsCOMPtr
<nsISHEntry
> entry
= new nsSHEntry(*this);
1028 entry
.forget(aResult
);
1033 nsSHEntry::GetSaveLayoutStateFlag(bool* aFlag
) {
1034 *aFlag
= mShared
->mSaveLayoutState
;
1039 nsSHEntry::SetSaveLayoutStateFlag(bool aFlag
) {
1040 mShared
->mSaveLayoutState
= aFlag
;
1041 if (mShared
->mLayoutHistoryState
) {
1042 mShared
->mLayoutHistoryState
->SetScrollPositionOnly(!aFlag
);
1049 nsSHEntry::SetWindowState(nsISupports
* aState
) {
1050 GetState()->mWindowState
= aState
;
1055 nsSHEntry::GetWindowState(nsISupports
** aState
) {
1056 NS_IF_ADDREF(*aState
= GetState()->mWindowState
);
1061 nsSHEntry::GetRefreshURIList(nsIMutableArray
** aList
) {
1062 NS_IF_ADDREF(*aList
= GetState()->mRefreshURIList
);
1067 nsSHEntry::SetRefreshURIList(nsIMutableArray
* aList
) {
1068 GetState()->mRefreshURIList
= aList
;
1072 NS_IMETHODIMP_(void)
1073 nsSHEntry::AddChildShell(nsIDocShellTreeItem
* aShell
) {
1074 MOZ_ASSERT(aShell
, "Null child shell added to history entry");
1075 GetState()->mChildShells
.AppendObject(aShell
);
1079 nsSHEntry::ChildShellAt(int32_t aIndex
, nsIDocShellTreeItem
** aShell
) {
1080 NS_IF_ADDREF(*aShell
= GetState()->mChildShells
.SafeObjectAt(aIndex
));
1084 NS_IMETHODIMP_(void)
1085 nsSHEntry::ClearChildShells() { GetState()->mChildShells
.Clear(); }
1087 NS_IMETHODIMP_(void)
1088 nsSHEntry::SyncPresentationState() { GetState()->SyncPresentationState(); }
1090 nsDocShellEditorData
* nsSHEntry::ForgetEditorData() {
1091 // XXX jlebar Check how this is used.
1092 return GetState()->mEditorData
.release();
1095 void nsSHEntry::SetEditorData(nsDocShellEditorData
* aData
) {
1096 NS_ASSERTION(!(aData
&& GetState()->mEditorData
),
1097 "We're going to overwrite an owning ref!");
1098 if (GetState()->mEditorData
!= aData
) {
1099 GetState()->mEditorData
= mozilla::WrapUnique(aData
);
1103 bool nsSHEntry::HasDetachedEditor() {
1104 return GetState()->mEditorData
!= nullptr;
1107 bool nsSHEntry::HasBFCacheEntry(
1108 mozilla::dom::SHEntrySharedParentState
* aEntry
) {
1109 return GetState() == aEntry
;
1113 nsSHEntry::AbandonBFCacheEntry() {
1114 mShared
= GetState()->Duplicate();
1119 nsSHEntry::GetBfcacheID(uint64_t* aBFCacheID
) {
1120 *aBFCacheID
= mShared
->GetId();
1125 nsSHEntry::GetWireframe(JSContext
* aCx
, JS::MutableHandle
<JS::Value
> aOut
) {
1126 aOut
.set(JS::NullValue());
1131 nsSHEntry::SetWireframe(JSContext
* aCx
, JS::Handle
<JS::Value
> aArg
) {
1132 return NS_ERROR_NOT_IMPLEMENTED
;