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/. */
6 
7 #include "SessionHistoryEntry.h"
8 #include "ipc/IPCMessageUtilsSpecializations.h"
9 #include "nsDocShell.h"
10 #include "nsDocShellLoadState.h"
11 #include "nsFrameLoader.h"
12 #include "nsIHttpChannel.h"
13 #include "nsIXULRuntime.h"
14 #include "nsSHEntryShared.h"
15 #include "nsSHistory.h"
16 #include "nsStructuredCloneContainer.h"
17 #include "nsXULAppAPI.h"
18 #include "mozilla/PresState.h"
19 #include "mozilla/StaticPrefs_fission.h"
20 #include "mozilla/Tuple.h"
21 #include "mozilla/dom/BrowserParent.h"
22 #include "mozilla/dom/ContentChild.h"
23 #include "mozilla/dom/ContentParent.h"
24 #include "mozilla/dom/CSPMessageUtils.h"
25 #include "mozilla/dom/DOMTypes.h"
26 #include "mozilla/dom/nsCSPContext.h"
27 #include "mozilla/dom/PermissionMessageUtils.h"
28 #include "mozilla/dom/ReferrerInfoUtils.h"
29 #include "mozilla/ipc/IPDLParamTraits.h"
30 #include "mozilla/ipc/ProtocolUtils.h"
31 #include "mozilla/ipc/URIUtils.h"
32 
33 extern mozilla::LazyLogModule gSHLog;
34 
35 namespace mozilla {
36 namespace dom {
37 
SessionHistoryInfo(nsDocShellLoadState * aLoadState,nsIChannel * aChannel)38 SessionHistoryInfo::SessionHistoryInfo(nsDocShellLoadState* aLoadState,
39                                        nsIChannel* aChannel)
40     : mURI(aLoadState->URI()),
41       mOriginalURI(aLoadState->OriginalURI()),
42       mResultPrincipalURI(aLoadState->ResultPrincipalURI()),
43       mPostData(aLoadState->PostDataStream()),
44       mLoadType(aLoadState->LoadType()),
45       mSrcdocData(aLoadState->SrcdocData().IsVoid()
46                       ? Nothing()
47                       : Some(aLoadState->SrcdocData())),
48       mBaseURI(aLoadState->BaseURI()),
49       mLoadReplace(aLoadState->LoadReplace()),
50       mHasUserInteraction(false),
51       mHasUserActivation(aLoadState->HasValidUserGestureActivation()),
52       mSharedState(SharedState::Create(
53           aLoadState->TriggeringPrincipal(), aLoadState->PrincipalToInherit(),
54           aLoadState->PartitionedPrincipalToInherit(), aLoadState->Csp(),
55           /* FIXME Is this correct? */
56           aLoadState->TypeHint())) {
57   if (nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel)) {
58     mReferrerInfo = httpChannel->GetReferrerInfo();
59   }
60 
61   MaybeUpdateTitleFromURI();
62 }
63 
SessionHistoryInfo(const SessionHistoryInfo & aSharedStateFrom,nsIURI * aURI)64 SessionHistoryInfo::SessionHistoryInfo(
65     const SessionHistoryInfo& aSharedStateFrom, nsIURI* aURI)
66     : mURI(aURI), mSharedState(aSharedStateFrom.mSharedState) {
67   MaybeUpdateTitleFromURI();
68 }
69 
SessionHistoryInfo(nsIURI * aURI,nsIPrincipal * aTriggeringPrincipal,nsIPrincipal * aPrincipalToInherit,nsIPrincipal * aPartitionedPrincipalToInherit,nsIContentSecurityPolicy * aCsp,const nsACString & aContentType)70 SessionHistoryInfo::SessionHistoryInfo(
71     nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal,
72     nsIPrincipal* aPrincipalToInherit,
73     nsIPrincipal* aPartitionedPrincipalToInherit,
74     nsIContentSecurityPolicy* aCsp, const nsACString& aContentType)
75     : mURI(aURI),
76       mSharedState(SharedState::Create(
77           aTriggeringPrincipal, aPrincipalToInherit,
78           aPartitionedPrincipalToInherit, aCsp, aContentType)) {
79   MaybeUpdateTitleFromURI();
80 }
81 
SessionHistoryInfo(nsIChannel * aChannel,uint32_t aLoadType,nsIPrincipal * aPartitionedPrincipalToInherit,nsIContentSecurityPolicy * aCsp)82 SessionHistoryInfo::SessionHistoryInfo(
83     nsIChannel* aChannel, uint32_t aLoadType,
84     nsIPrincipal* aPartitionedPrincipalToInherit,
85     nsIContentSecurityPolicy* aCsp) {
86   aChannel->GetURI(getter_AddRefs(mURI));
87   mLoadType = aLoadType;
88 
89   nsCOMPtr<nsILoadInfo> loadInfo;
90   aChannel->GetLoadInfo(getter_AddRefs(loadInfo));
91 
92   loadInfo->GetResultPrincipalURI(getter_AddRefs(mResultPrincipalURI));
93   loadInfo->GetTriggeringPrincipal(
94       getter_AddRefs(mSharedState.Get()->mTriggeringPrincipal));
95   loadInfo->GetPrincipalToInherit(
96       getter_AddRefs(mSharedState.Get()->mPrincipalToInherit));
97 
98   mSharedState.Get()->mPartitionedPrincipalToInherit =
99       aPartitionedPrincipalToInherit;
100   mSharedState.Get()->mCsp = aCsp;
101   aChannel->GetContentType(mSharedState.Get()->mContentType);
102   aChannel->GetOriginalURI(getter_AddRefs(mOriginalURI));
103 
104   uint32_t loadFlags;
105   aChannel->GetLoadFlags(&loadFlags);
106   mLoadReplace = !!(loadFlags & nsIChannel::LOAD_REPLACE);
107 
108   MaybeUpdateTitleFromURI();
109 
110   if (nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel)) {
111     mReferrerInfo = httpChannel->GetReferrerInfo();
112   }
113 }
114 
Reset(nsIURI * aURI,const nsID & aDocShellID,bool aDynamicCreation,nsIPrincipal * aTriggeringPrincipal,nsIPrincipal * aPrincipalToInherit,nsIPrincipal * aPartitionedPrincipalToInherit,nsIContentSecurityPolicy * aCsp,const nsACString & aContentType)115 void SessionHistoryInfo::Reset(nsIURI* aURI, const nsID& aDocShellID,
116                                bool aDynamicCreation,
117                                nsIPrincipal* aTriggeringPrincipal,
118                                nsIPrincipal* aPrincipalToInherit,
119                                nsIPrincipal* aPartitionedPrincipalToInherit,
120                                nsIContentSecurityPolicy* aCsp,
121                                const nsACString& aContentType) {
122   mURI = aURI;
123   mOriginalURI = nullptr;
124   mResultPrincipalURI = nullptr;
125   mReferrerInfo = nullptr;
126   // Default title is the URL.
127   nsAutoCString spec;
128   if (NS_SUCCEEDED(mURI->GetSpec(spec))) {
129     CopyUTF8toUTF16(spec, mTitle);
130   }
131   mPostData = nullptr;
132   mLoadType = 0;
133   mScrollPositionX = 0;
134   mScrollPositionY = 0;
135   mStateData = nullptr;
136   mSrcdocData = Nothing();
137   mBaseURI = nullptr;
138   mLoadReplace = false;
139   mURIWasModified = false;
140   mScrollRestorationIsManual = false;
141   mPersist = false;
142   mHasUserInteraction = false;
143   mHasUserActivation = false;
144 
145   mSharedState.Get()->mTriggeringPrincipal = aTriggeringPrincipal;
146   mSharedState.Get()->mPrincipalToInherit = aPrincipalToInherit;
147   mSharedState.Get()->mPartitionedPrincipalToInherit =
148       aPartitionedPrincipalToInherit;
149   mSharedState.Get()->mCsp = aCsp;
150   mSharedState.Get()->mContentType = aContentType;
151   mSharedState.Get()->mLayoutHistoryState = nullptr;
152 }
153 
MaybeUpdateTitleFromURI()154 void SessionHistoryInfo::MaybeUpdateTitleFromURI() {
155   if (mTitle.IsEmpty() && mURI) {
156     // Default title is the URL.
157     nsAutoCString spec;
158     if (NS_SUCCEEDED(mURI->GetSpec(spec))) {
159       AppendUTF8toUTF16(spec, mTitle);
160     }
161   }
162 }
163 
SharedId() const164 uint64_t SessionHistoryInfo::SharedId() const {
165   return mSharedState.Get()->mId;
166 }
167 
GetLayoutHistoryState()168 nsILayoutHistoryState* SessionHistoryInfo::GetLayoutHistoryState() {
169   return mSharedState.Get()->mLayoutHistoryState;
170 }
171 
SetLayoutHistoryState(nsILayoutHistoryState * aState)172 void SessionHistoryInfo::SetLayoutHistoryState(nsILayoutHistoryState* aState) {
173   mSharedState.Get()->mLayoutHistoryState = aState;
174 }
175 
GetTriggeringPrincipal() const176 nsIPrincipal* SessionHistoryInfo::GetTriggeringPrincipal() const {
177   return mSharedState.Get()->mTriggeringPrincipal;
178 }
179 
GetPrincipalToInherit() const180 nsIPrincipal* SessionHistoryInfo::GetPrincipalToInherit() const {
181   return mSharedState.Get()->mPrincipalToInherit;
182 }
183 
GetPartitionedPrincipalToInherit() const184 nsIPrincipal* SessionHistoryInfo::GetPartitionedPrincipalToInherit() const {
185   return mSharedState.Get()->mPartitionedPrincipalToInherit;
186 }
187 
GetCsp() const188 nsIContentSecurityPolicy* SessionHistoryInfo::GetCsp() const {
189   return mSharedState.Get()->mCsp;
190 }
191 
GetCacheKey() const192 uint32_t SessionHistoryInfo::GetCacheKey() const {
193   return mSharedState.Get()->mCacheKey;
194 }
195 
SetCacheKey(uint32_t aCacheKey)196 void SessionHistoryInfo::SetCacheKey(uint32_t aCacheKey) {
197   mSharedState.Get()->mCacheKey = aCacheKey;
198 }
199 
IsSubFrame() const200 bool SessionHistoryInfo::IsSubFrame() const {
201   return mSharedState.Get()->mIsFrameNavigation;
202 }
203 
SetSaveLayoutStateFlag(bool aSaveLayoutStateFlag)204 void SessionHistoryInfo::SetSaveLayoutStateFlag(bool aSaveLayoutStateFlag) {
205   MOZ_ASSERT(XRE_IsParentProcess());
206   static_cast<SHEntrySharedParentState*>(mSharedState.Get())->mSaveLayoutState =
207       aSaveLayoutStateFlag;
208 }
209 
FillLoadInfo(nsDocShellLoadState & aLoadState) const210 void SessionHistoryInfo::FillLoadInfo(nsDocShellLoadState& aLoadState) const {
211   aLoadState.SetOriginalURI(mOriginalURI);
212   aLoadState.SetMaybeResultPrincipalURI(Some(mResultPrincipalURI));
213   aLoadState.SetLoadReplace(mLoadReplace);
214   aLoadState.SetPostDataStream(mPostData);
215   aLoadState.SetReferrerInfo(mReferrerInfo);
216 
217   aLoadState.SetTypeHint(mSharedState.Get()->mContentType);
218   aLoadState.SetTriggeringPrincipal(mSharedState.Get()->mTriggeringPrincipal);
219   aLoadState.SetPrincipalToInherit(mSharedState.Get()->mPrincipalToInherit);
220   aLoadState.SetPartitionedPrincipalToInherit(
221       mSharedState.Get()->mPartitionedPrincipalToInherit);
222   aLoadState.SetCsp(mSharedState.Get()->mCsp);
223 
224   // Do not inherit principal from document (security-critical!);
225   uint32_t flags = nsDocShell::InternalLoad::INTERNAL_LOAD_FLAGS_NONE;
226 
227   // Passing nullptr as aSourceDocShell gives the same behaviour as before
228   // aSourceDocShell was introduced. According to spec we should be passing
229   // the source browsing context that was used when the history entry was
230   // first created. bug 947716 has been created to address this issue.
231   nsAutoString srcdoc;
232   nsCOMPtr<nsIURI> baseURI;
233   if (mSrcdocData) {
234     srcdoc = mSrcdocData.value();
235     baseURI = mBaseURI;
236     flags |= nsDocShell::InternalLoad::INTERNAL_LOAD_FLAGS_IS_SRCDOC;
237   } else {
238     srcdoc = VoidString();
239   }
240   aLoadState.SetSrcdocData(srcdoc);
241   aLoadState.SetBaseURI(baseURI);
242   aLoadState.SetInternalLoadFlags(flags);
243 
244   aLoadState.SetFirstParty(true);
245 }
246 /* static */
Create(nsIPrincipal * aTriggeringPrincipal,nsIPrincipal * aPrincipalToInherit,nsIPrincipal * aPartitionedPrincipalToInherit,nsIContentSecurityPolicy * aCsp,const nsACString & aContentType)247 SessionHistoryInfo::SharedState SessionHistoryInfo::SharedState::Create(
248     nsIPrincipal* aTriggeringPrincipal, nsIPrincipal* aPrincipalToInherit,
249     nsIPrincipal* aPartitionedPrincipalToInherit,
250     nsIContentSecurityPolicy* aCsp, const nsACString& aContentType) {
251   if (XRE_IsParentProcess()) {
252     return SharedState(new SHEntrySharedParentState(
253         aTriggeringPrincipal, aPrincipalToInherit,
254         aPartitionedPrincipalToInherit, aCsp, aContentType));
255   }
256 
257   return SharedState(MakeUnique<SHEntrySharedState>(
258       aTriggeringPrincipal, aPrincipalToInherit, aPartitionedPrincipalToInherit,
259       aCsp, aContentType));
260 }
261 
SharedState()262 SessionHistoryInfo::SharedState::SharedState() { Init(); }
263 
SharedState(const SessionHistoryInfo::SharedState & aOther)264 SessionHistoryInfo::SharedState::SharedState(
265     const SessionHistoryInfo::SharedState& aOther) {
266   Init(aOther);
267 }
268 
SharedState(const Maybe<const SessionHistoryInfo::SharedState &> & aOther)269 SessionHistoryInfo::SharedState::SharedState(
270     const Maybe<const SessionHistoryInfo::SharedState&>& aOther) {
271   if (aOther.isSome()) {
272     Init(aOther.ref());
273   } else {
274     Init();
275   }
276 }
277 
~SharedState()278 SessionHistoryInfo::SharedState::~SharedState() {
279   if (XRE_IsParentProcess()) {
280     mParent
281         .RefPtr<SHEntrySharedParentState>::~RefPtr<SHEntrySharedParentState>();
282   } else {
283     mChild.UniquePtr<SHEntrySharedState>::~UniquePtr<SHEntrySharedState>();
284   }
285 }
286 
operator =(const SessionHistoryInfo::SharedState & aOther)287 SessionHistoryInfo::SharedState& SessionHistoryInfo::SharedState::operator=(
288     const SessionHistoryInfo::SharedState& aOther) {
289   if (this != &aOther) {
290     if (XRE_IsParentProcess()) {
291       mParent = aOther.mParent;
292     } else {
293       mChild = MakeUnique<SHEntrySharedState>(*aOther.mChild);
294     }
295   }
296   return *this;
297 }
298 
Get() const299 SHEntrySharedState* SessionHistoryInfo::SharedState::Get() const {
300   if (XRE_IsParentProcess()) {
301     return mParent;
302   }
303 
304   return mChild.get();
305 }
306 
ChangeId(uint64_t aId)307 void SessionHistoryInfo::SharedState::ChangeId(uint64_t aId) {
308   if (XRE_IsParentProcess()) {
309     mParent->ChangeId(aId);
310   } else {
311     mChild->mId = aId;
312   }
313 }
314 
Init()315 void SessionHistoryInfo::SharedState::Init() {
316   if (XRE_IsParentProcess()) {
317     new (&mParent)
318         RefPtr<SHEntrySharedParentState>(new SHEntrySharedParentState());
319   } else {
320     new (&mChild)
321         UniquePtr<SHEntrySharedState>(MakeUnique<SHEntrySharedState>());
322   }
323 }
324 
Init(const SessionHistoryInfo::SharedState & aOther)325 void SessionHistoryInfo::SharedState::Init(
326     const SessionHistoryInfo::SharedState& aOther) {
327   if (XRE_IsParentProcess()) {
328     new (&mParent) RefPtr<SHEntrySharedParentState>(aOther.mParent);
329   } else {
330     new (&mChild) UniquePtr<SHEntrySharedState>(
331         MakeUnique<SHEntrySharedState>(*aOther.mChild));
332   }
333 }
334 
335 static uint64_t gLoadingSessionHistoryInfoLoadId = 0;
336 
337 nsTHashMap<nsUint64HashKey, SessionHistoryEntry*>*
338     SessionHistoryEntry::sLoadIdToEntry = nullptr;
339 
LoadingSessionHistoryInfo(SessionHistoryEntry * aEntry)340 LoadingSessionHistoryInfo::LoadingSessionHistoryInfo(
341     SessionHistoryEntry* aEntry)
342     : mInfo(aEntry->Info()), mLoadId(++gLoadingSessionHistoryInfoLoadId) {
343   SessionHistoryEntry::SetByLoadId(mLoadId, aEntry);
344 }
345 
LoadingSessionHistoryInfo(SessionHistoryEntry * aEntry,LoadingSessionHistoryInfo * aInfo)346 LoadingSessionHistoryInfo::LoadingSessionHistoryInfo(
347     SessionHistoryEntry* aEntry, LoadingSessionHistoryInfo* aInfo)
348     : mInfo(aEntry->Info()),
349       mLoadId(aInfo->mLoadId),
350       mLoadIsFromSessionHistory(aInfo->mLoadIsFromSessionHistory),
351       mRequestedIndex(aInfo->mRequestedIndex),
352       mSessionHistoryLength(aInfo->mSessionHistoryLength),
353       mLoadingCurrentActiveEntry(aInfo->mLoadingCurrentActiveEntry) {
354   MOZ_ASSERT(SessionHistoryEntry::sLoadIdToEntry &&
355              SessionHistoryEntry::sLoadIdToEntry->Get(mLoadId) == aEntry);
356 }
357 
LoadingSessionHistoryInfo(const SessionHistoryInfo & aInfo)358 LoadingSessionHistoryInfo::LoadingSessionHistoryInfo(
359     const SessionHistoryInfo& aInfo)
360     : mInfo(aInfo), mLoadId(UINT64_MAX) {}
361 
362 already_AddRefed<nsDocShellLoadState>
CreateLoadInfo() const363 LoadingSessionHistoryInfo::CreateLoadInfo() const {
364   RefPtr<nsDocShellLoadState> loadState(
365       new nsDocShellLoadState(mInfo.GetURI()));
366 
367   mInfo.FillLoadInfo(*loadState);
368 
369   loadState->SetLoadingSessionHistoryInfo(*this);
370 
371   return loadState.forget();
372 }
373 
374 static uint32_t gEntryID;
375 
GetByLoadId(uint64_t aLoadId)376 SessionHistoryEntry* SessionHistoryEntry::GetByLoadId(uint64_t aLoadId) {
377   MOZ_ASSERT(XRE_IsParentProcess());
378   if (!sLoadIdToEntry) {
379     return nullptr;
380   }
381 
382   return sLoadIdToEntry->Get(aLoadId);
383 }
384 
SetByLoadId(uint64_t aLoadId,SessionHistoryEntry * aEntry)385 void SessionHistoryEntry::SetByLoadId(uint64_t aLoadId,
386                                       SessionHistoryEntry* aEntry) {
387   if (!sLoadIdToEntry) {
388     sLoadIdToEntry = new nsTHashMap<nsUint64HashKey, SessionHistoryEntry*>();
389   }
390 
391   MOZ_LOG(
392       gSHLog, LogLevel::Verbose,
393       ("SessionHistoryEntry::SetByLoadId(%" PRIu64 " - %p)", aLoadId, aEntry));
394   sLoadIdToEntry->InsertOrUpdate(aLoadId, aEntry);
395 }
396 
RemoveLoadId(uint64_t aLoadId)397 void SessionHistoryEntry::RemoveLoadId(uint64_t aLoadId) {
398   MOZ_ASSERT(XRE_IsParentProcess());
399   if (!sLoadIdToEntry) {
400     return;
401   }
402 
403   MOZ_LOG(gSHLog, LogLevel::Verbose,
404           ("SHEntry::RemoveLoadId(%" PRIu64 ")", aLoadId));
405   sLoadIdToEntry->Remove(aLoadId);
406 }
407 
SessionHistoryEntry()408 SessionHistoryEntry::SessionHistoryEntry()
409     : mInfo(new SessionHistoryInfo()), mID(++gEntryID) {
410   MOZ_ASSERT(mozilla::SessionHistoryInParent());
411 }
412 
SessionHistoryEntry(nsDocShellLoadState * aLoadState,nsIChannel * aChannel)413 SessionHistoryEntry::SessionHistoryEntry(nsDocShellLoadState* aLoadState,
414                                          nsIChannel* aChannel)
415     : mInfo(new SessionHistoryInfo(aLoadState, aChannel)), mID(++gEntryID) {
416   MOZ_ASSERT(mozilla::SessionHistoryInParent());
417 }
418 
SessionHistoryEntry(SessionHistoryInfo * aInfo)419 SessionHistoryEntry::SessionHistoryEntry(SessionHistoryInfo* aInfo)
420     : mInfo(MakeUnique<SessionHistoryInfo>(*aInfo)), mID(++gEntryID) {
421   MOZ_ASSERT(mozilla::SessionHistoryInParent());
422 }
423 
SessionHistoryEntry(const SessionHistoryEntry & aEntry)424 SessionHistoryEntry::SessionHistoryEntry(const SessionHistoryEntry& aEntry)
425     : mInfo(MakeUnique<SessionHistoryInfo>(*aEntry.mInfo)),
426       mParent(aEntry.mParent),
427       mID(aEntry.mID),
428       mBCHistoryLength(aEntry.mBCHistoryLength) {
429   MOZ_ASSERT(mozilla::SessionHistoryInParent());
430 }
431 
~SessionHistoryEntry()432 SessionHistoryEntry::~SessionHistoryEntry() {
433   // Null out the mParent pointers on all our kids.
434   for (nsISHEntry* entry : mChildren) {
435     if (entry) {
436       entry->SetParent(nullptr);
437     }
438   }
439 
440   if (sLoadIdToEntry) {
441     sLoadIdToEntry->RemoveIf(
442         [this](auto& aIter) { return aIter.Data() == this; });
443     if (sLoadIdToEntry->IsEmpty()) {
444       delete sLoadIdToEntry;
445       sLoadIdToEntry = nullptr;
446     }
447   }
448 }
449 
NS_IMPL_ISUPPORTS(SessionHistoryEntry,nsISHEntry,SessionHistoryEntry)450 NS_IMPL_ISUPPORTS(SessionHistoryEntry, nsISHEntry, SessionHistoryEntry)
451 
452 NS_IMETHODIMP
453 SessionHistoryEntry::GetURI(nsIURI** aURI) {
454   nsCOMPtr<nsIURI> uri = mInfo->mURI;
455   uri.forget(aURI);
456   return NS_OK;
457 }
458 
459 NS_IMETHODIMP
SetURI(nsIURI * aURI)460 SessionHistoryEntry::SetURI(nsIURI* aURI) {
461   mInfo->mURI = aURI;
462   return NS_OK;
463 }
464 
465 NS_IMETHODIMP
GetOriginalURI(nsIURI ** aOriginalURI)466 SessionHistoryEntry::GetOriginalURI(nsIURI** aOriginalURI) {
467   nsCOMPtr<nsIURI> originalURI = mInfo->mOriginalURI;
468   originalURI.forget(aOriginalURI);
469   return NS_OK;
470 }
471 
472 NS_IMETHODIMP
SetOriginalURI(nsIURI * aOriginalURI)473 SessionHistoryEntry::SetOriginalURI(nsIURI* aOriginalURI) {
474   mInfo->mOriginalURI = aOriginalURI;
475   return NS_OK;
476 }
477 
478 NS_IMETHODIMP
GetResultPrincipalURI(nsIURI ** aResultPrincipalURI)479 SessionHistoryEntry::GetResultPrincipalURI(nsIURI** aResultPrincipalURI) {
480   nsCOMPtr<nsIURI> resultPrincipalURI = mInfo->mResultPrincipalURI;
481   resultPrincipalURI.forget(aResultPrincipalURI);
482   return NS_OK;
483 }
484 
485 NS_IMETHODIMP
SetResultPrincipalURI(nsIURI * aResultPrincipalURI)486 SessionHistoryEntry::SetResultPrincipalURI(nsIURI* aResultPrincipalURI) {
487   mInfo->mResultPrincipalURI = aResultPrincipalURI;
488   return NS_OK;
489 }
490 
491 NS_IMETHODIMP
GetLoadReplace(bool * aLoadReplace)492 SessionHistoryEntry::GetLoadReplace(bool* aLoadReplace) {
493   *aLoadReplace = mInfo->mLoadReplace;
494   return NS_OK;
495 }
496 
497 NS_IMETHODIMP
SetLoadReplace(bool aLoadReplace)498 SessionHistoryEntry::SetLoadReplace(bool aLoadReplace) {
499   mInfo->mLoadReplace = aLoadReplace;
500   return NS_OK;
501 }
502 
503 NS_IMETHODIMP
GetTitle(nsAString & aTitle)504 SessionHistoryEntry::GetTitle(nsAString& aTitle) {
505   aTitle = mInfo->mTitle;
506   return NS_OK;
507 }
508 
509 NS_IMETHODIMP
SetTitle(const nsAString & aTitle)510 SessionHistoryEntry::SetTitle(const nsAString& aTitle) {
511   mInfo->SetTitle(aTitle);
512   return NS_OK;
513 }
514 
515 NS_IMETHODIMP
GetName(nsAString & aName)516 SessionHistoryEntry::GetName(nsAString& aName) {
517   aName = mInfo->mName;
518   return NS_OK;
519 }
520 
521 NS_IMETHODIMP
SetName(const nsAString & aName)522 SessionHistoryEntry::SetName(const nsAString& aName) {
523   mInfo->mName = aName;
524   return NS_OK;
525 }
526 
527 NS_IMETHODIMP
GetIsSubFrame(bool * aIsSubFrame)528 SessionHistoryEntry::GetIsSubFrame(bool* aIsSubFrame) {
529   *aIsSubFrame = SharedInfo()->mIsFrameNavigation;
530   return NS_OK;
531 }
532 
533 NS_IMETHODIMP
SetIsSubFrame(bool aIsSubFrame)534 SessionHistoryEntry::SetIsSubFrame(bool aIsSubFrame) {
535   SharedInfo()->mIsFrameNavigation = aIsSubFrame;
536   return NS_OK;
537 }
538 
539 NS_IMETHODIMP
GetHasUserInteraction(bool * aFlag)540 SessionHistoryEntry::GetHasUserInteraction(bool* aFlag) {
541   // The back button and menulist deal with root/top-level
542   // session history entries, thus we annotate only the root entry.
543   if (!mParent) {
544     *aFlag = mInfo->mHasUserInteraction;
545   } else {
546     nsCOMPtr<nsISHEntry> root = nsSHistory::GetRootSHEntry(this);
547     root->GetHasUserInteraction(aFlag);
548   }
549   return NS_OK;
550 }
551 
552 NS_IMETHODIMP
SetHasUserInteraction(bool aFlag)553 SessionHistoryEntry::SetHasUserInteraction(bool aFlag) {
554   // The back button and menulist deal with root/top-level
555   // session history entries, thus we annotate only the root entry.
556   if (!mParent) {
557     mInfo->mHasUserInteraction = aFlag;
558   } else {
559     nsCOMPtr<nsISHEntry> root = nsSHistory::GetRootSHEntry(this);
560     root->SetHasUserInteraction(aFlag);
561   }
562   return NS_OK;
563 }
564 
565 NS_IMETHODIMP
GetHasUserActivation(bool * aFlag)566 SessionHistoryEntry::GetHasUserActivation(bool* aFlag) {
567   *aFlag = mInfo->mHasUserActivation;
568   return NS_OK;
569 }
570 
571 NS_IMETHODIMP
SetHasUserActivation(bool aFlag)572 SessionHistoryEntry::SetHasUserActivation(bool aFlag) {
573   mInfo->mHasUserActivation = aFlag;
574   return NS_OK;
575 }
576 
577 NS_IMETHODIMP
GetReferrerInfo(nsIReferrerInfo ** aReferrerInfo)578 SessionHistoryEntry::GetReferrerInfo(nsIReferrerInfo** aReferrerInfo) {
579   nsCOMPtr<nsIReferrerInfo> referrerInfo = mInfo->mReferrerInfo;
580   referrerInfo.forget(aReferrerInfo);
581   return NS_OK;
582 }
583 
584 NS_IMETHODIMP
SetReferrerInfo(nsIReferrerInfo * aReferrerInfo)585 SessionHistoryEntry::SetReferrerInfo(nsIReferrerInfo* aReferrerInfo) {
586   mInfo->mReferrerInfo = aReferrerInfo;
587   return NS_OK;
588 }
589 
590 NS_IMETHODIMP
GetContentViewer(nsIContentViewer ** aContentViewer)591 SessionHistoryEntry::GetContentViewer(nsIContentViewer** aContentViewer) {
592   *aContentViewer = nullptr;
593   return NS_OK;
594 }
595 
596 NS_IMETHODIMP
SetContentViewer(nsIContentViewer * aContentViewer)597 SessionHistoryEntry::SetContentViewer(nsIContentViewer* aContentViewer) {
598   MOZ_CRASH("This lives in the child process");
599   return NS_ERROR_FAILURE;
600 }
601 
602 NS_IMETHODIMP
GetSticky(bool * aSticky)603 SessionHistoryEntry::GetSticky(bool* aSticky) {
604   *aSticky = SharedInfo()->mSticky;
605   return NS_OK;
606 }
607 
608 NS_IMETHODIMP
SetSticky(bool aSticky)609 SessionHistoryEntry::SetSticky(bool aSticky) {
610   SharedInfo()->mSticky = aSticky;
611   return NS_OK;
612 }
613 
614 NS_IMETHODIMP
GetWindowState(nsISupports ** aWindowState)615 SessionHistoryEntry::GetWindowState(nsISupports** aWindowState) {
616   MOZ_CRASH("This lives in the child process");
617   return NS_ERROR_FAILURE;
618 }
619 
620 NS_IMETHODIMP
SetWindowState(nsISupports * aWindowState)621 SessionHistoryEntry::SetWindowState(nsISupports* aWindowState) {
622   MOZ_CRASH("This lives in the child process");
623   return NS_ERROR_FAILURE;
624 }
625 
626 NS_IMETHODIMP
GetRefreshURIList(nsIMutableArray ** aRefreshURIList)627 SessionHistoryEntry::GetRefreshURIList(nsIMutableArray** aRefreshURIList) {
628   MOZ_CRASH("This lives in the child process");
629   return NS_ERROR_FAILURE;
630 }
631 
632 NS_IMETHODIMP
SetRefreshURIList(nsIMutableArray * aRefreshURIList)633 SessionHistoryEntry::SetRefreshURIList(nsIMutableArray* aRefreshURIList) {
634   MOZ_CRASH("This lives in the child process");
635   return NS_ERROR_FAILURE;
636 }
637 
638 NS_IMETHODIMP
GetPostData(nsIInputStream ** aPostData)639 SessionHistoryEntry::GetPostData(nsIInputStream** aPostData) {
640   nsCOMPtr<nsIInputStream> postData = mInfo->mPostData;
641   postData.forget(aPostData);
642   return NS_OK;
643 }
644 
645 NS_IMETHODIMP
SetPostData(nsIInputStream * aPostData)646 SessionHistoryEntry::SetPostData(nsIInputStream* aPostData) {
647   mInfo->mPostData = aPostData;
648   return NS_OK;
649 }
650 
651 NS_IMETHODIMP
GetLayoutHistoryState(nsILayoutHistoryState ** aLayoutHistoryState)652 SessionHistoryEntry::GetLayoutHistoryState(
653     nsILayoutHistoryState** aLayoutHistoryState) {
654   nsCOMPtr<nsILayoutHistoryState> layoutHistoryState =
655       SharedInfo()->mLayoutHistoryState;
656   layoutHistoryState.forget(aLayoutHistoryState);
657   return NS_OK;
658 }
659 
660 NS_IMETHODIMP
SetLayoutHistoryState(nsILayoutHistoryState * aLayoutHistoryState)661 SessionHistoryEntry::SetLayoutHistoryState(
662     nsILayoutHistoryState* aLayoutHistoryState) {
663   SharedInfo()->mLayoutHistoryState = aLayoutHistoryState;
664   return NS_OK;
665 }
666 
667 NS_IMETHODIMP
GetParent(nsISHEntry ** aParent)668 SessionHistoryEntry::GetParent(nsISHEntry** aParent) {
669   nsCOMPtr<nsISHEntry> parent = mParent;
670   parent.forget(aParent);
671   return NS_OK;
672 }
673 
674 NS_IMETHODIMP
SetParent(nsISHEntry * aParent)675 SessionHistoryEntry::SetParent(nsISHEntry* aParent) {
676   mParent = aParent;
677   return NS_OK;
678 }
679 
680 NS_IMETHODIMP
GetLoadType(uint32_t * aLoadType)681 SessionHistoryEntry::GetLoadType(uint32_t* aLoadType) {
682   *aLoadType = mInfo->mLoadType;
683   return NS_OK;
684 }
685 
686 NS_IMETHODIMP
SetLoadType(uint32_t aLoadType)687 SessionHistoryEntry::SetLoadType(uint32_t aLoadType) {
688   mInfo->mLoadType = aLoadType;
689   return NS_OK;
690 }
691 
692 NS_IMETHODIMP
GetID(uint32_t * aID)693 SessionHistoryEntry::GetID(uint32_t* aID) {
694   *aID = mID;
695   return NS_OK;
696 }
697 
698 NS_IMETHODIMP
SetID(uint32_t aID)699 SessionHistoryEntry::SetID(uint32_t aID) {
700   mID = aID;
701   return NS_OK;
702 }
703 
704 NS_IMETHODIMP
GetCacheKey(uint32_t * aCacheKey)705 SessionHistoryEntry::GetCacheKey(uint32_t* aCacheKey) {
706   *aCacheKey = SharedInfo()->mCacheKey;
707   return NS_OK;
708 }
709 
710 NS_IMETHODIMP
SetCacheKey(uint32_t aCacheKey)711 SessionHistoryEntry::SetCacheKey(uint32_t aCacheKey) {
712   SharedInfo()->mCacheKey = aCacheKey;
713   return NS_OK;
714 }
715 
716 NS_IMETHODIMP
GetSaveLayoutStateFlag(bool * aSaveLayoutStateFlag)717 SessionHistoryEntry::GetSaveLayoutStateFlag(bool* aSaveLayoutStateFlag) {
718   *aSaveLayoutStateFlag = SharedInfo()->mSaveLayoutState;
719   return NS_OK;
720 }
721 
722 NS_IMETHODIMP
SetSaveLayoutStateFlag(bool aSaveLayoutStateFlag)723 SessionHistoryEntry::SetSaveLayoutStateFlag(bool aSaveLayoutStateFlag) {
724   SharedInfo()->mSaveLayoutState = aSaveLayoutStateFlag;
725   return NS_OK;
726 }
727 
728 NS_IMETHODIMP
GetContentType(nsACString & aContentType)729 SessionHistoryEntry::GetContentType(nsACString& aContentType) {
730   aContentType = SharedInfo()->mContentType;
731   return NS_OK;
732 }
733 
734 NS_IMETHODIMP
SetContentType(const nsACString & aContentType)735 SessionHistoryEntry::SetContentType(const nsACString& aContentType) {
736   SharedInfo()->mContentType = aContentType;
737   return NS_OK;
738 }
739 
740 NS_IMETHODIMP
GetURIWasModified(bool * aURIWasModified)741 SessionHistoryEntry::GetURIWasModified(bool* aURIWasModified) {
742   *aURIWasModified = mInfo->mURIWasModified;
743   return NS_OK;
744 }
745 
746 NS_IMETHODIMP
SetURIWasModified(bool aURIWasModified)747 SessionHistoryEntry::SetURIWasModified(bool aURIWasModified) {
748   mInfo->mURIWasModified = aURIWasModified;
749   return NS_OK;
750 }
751 
752 NS_IMETHODIMP
GetTriggeringPrincipal(nsIPrincipal ** aTriggeringPrincipal)753 SessionHistoryEntry::GetTriggeringPrincipal(
754     nsIPrincipal** aTriggeringPrincipal) {
755   nsCOMPtr<nsIPrincipal> triggeringPrincipal =
756       SharedInfo()->mTriggeringPrincipal;
757   triggeringPrincipal.forget(aTriggeringPrincipal);
758   return NS_OK;
759 }
760 
761 NS_IMETHODIMP
SetTriggeringPrincipal(nsIPrincipal * aTriggeringPrincipal)762 SessionHistoryEntry::SetTriggeringPrincipal(
763     nsIPrincipal* aTriggeringPrincipal) {
764   SharedInfo()->mTriggeringPrincipal = aTriggeringPrincipal;
765   return NS_OK;
766 }
767 
768 NS_IMETHODIMP
GetPrincipalToInherit(nsIPrincipal ** aPrincipalToInherit)769 SessionHistoryEntry::GetPrincipalToInherit(nsIPrincipal** aPrincipalToInherit) {
770   nsCOMPtr<nsIPrincipal> principalToInherit = SharedInfo()->mPrincipalToInherit;
771   principalToInherit.forget(aPrincipalToInherit);
772   return NS_OK;
773 }
774 
775 NS_IMETHODIMP
SetPrincipalToInherit(nsIPrincipal * aPrincipalToInherit)776 SessionHistoryEntry::SetPrincipalToInherit(nsIPrincipal* aPrincipalToInherit) {
777   SharedInfo()->mPrincipalToInherit = aPrincipalToInherit;
778   return NS_OK;
779 }
780 
781 NS_IMETHODIMP
GetPartitionedPrincipalToInherit(nsIPrincipal ** aPartitionedPrincipalToInherit)782 SessionHistoryEntry::GetPartitionedPrincipalToInherit(
783     nsIPrincipal** aPartitionedPrincipalToInherit) {
784   nsCOMPtr<nsIPrincipal> partitionedPrincipalToInherit =
785       SharedInfo()->mPartitionedPrincipalToInherit;
786   partitionedPrincipalToInherit.forget(aPartitionedPrincipalToInherit);
787   return NS_OK;
788 }
789 
790 NS_IMETHODIMP
SetPartitionedPrincipalToInherit(nsIPrincipal * aPartitionedPrincipalToInherit)791 SessionHistoryEntry::SetPartitionedPrincipalToInherit(
792     nsIPrincipal* aPartitionedPrincipalToInherit) {
793   SharedInfo()->mPartitionedPrincipalToInherit = aPartitionedPrincipalToInherit;
794   return NS_OK;
795 }
796 
797 NS_IMETHODIMP
GetCsp(nsIContentSecurityPolicy ** aCsp)798 SessionHistoryEntry::GetCsp(nsIContentSecurityPolicy** aCsp) {
799   nsCOMPtr<nsIContentSecurityPolicy> csp = SharedInfo()->mCsp;
800   csp.forget(aCsp);
801   return NS_OK;
802 }
803 
804 NS_IMETHODIMP
SetCsp(nsIContentSecurityPolicy * aCsp)805 SessionHistoryEntry::SetCsp(nsIContentSecurityPolicy* aCsp) {
806   SharedInfo()->mCsp = aCsp;
807   return NS_OK;
808 }
809 
810 NS_IMETHODIMP
GetStateData(nsIStructuredCloneContainer ** aStateData)811 SessionHistoryEntry::GetStateData(nsIStructuredCloneContainer** aStateData) {
812   RefPtr<nsStructuredCloneContainer> stateData = mInfo->mStateData;
813   stateData.forget(aStateData);
814   return NS_OK;
815 }
816 
817 NS_IMETHODIMP
SetStateData(nsIStructuredCloneContainer * aStateData)818 SessionHistoryEntry::SetStateData(nsIStructuredCloneContainer* aStateData) {
819   mInfo->mStateData = static_cast<nsStructuredCloneContainer*>(aStateData);
820   return NS_OK;
821 }
822 
DocshellID() const823 const nsID& SessionHistoryEntry::DocshellID() const {
824   return SharedInfo()->mDocShellID;
825 }
826 
827 NS_IMETHODIMP
GetDocshellID(nsID & aDocshellID)828 SessionHistoryEntry::GetDocshellID(nsID& aDocshellID) {
829   aDocshellID = DocshellID();
830   return NS_OK;
831 }
832 
833 NS_IMETHODIMP
SetDocshellID(const nsID & aDocshellID)834 SessionHistoryEntry::SetDocshellID(const nsID& aDocshellID) {
835   SharedInfo()->mDocShellID = aDocshellID;
836   return NS_OK;
837 }
838 
839 NS_IMETHODIMP
GetIsSrcdocEntry(bool * aIsSrcdocEntry)840 SessionHistoryEntry::GetIsSrcdocEntry(bool* aIsSrcdocEntry) {
841   *aIsSrcdocEntry = mInfo->mSrcdocData.isSome();
842   return NS_OK;
843 }
844 
845 NS_IMETHODIMP
GetSrcdocData(nsAString & aSrcdocData)846 SessionHistoryEntry::GetSrcdocData(nsAString& aSrcdocData) {
847   aSrcdocData = mInfo->mSrcdocData.valueOr(EmptyString());
848   return NS_OK;
849 }
850 
851 NS_IMETHODIMP
SetSrcdocData(const nsAString & aSrcdocData)852 SessionHistoryEntry::SetSrcdocData(const nsAString& aSrcdocData) {
853   mInfo->mSrcdocData = Some(nsString(aSrcdocData));
854   return NS_OK;
855 }
856 
857 NS_IMETHODIMP
GetBaseURI(nsIURI ** aBaseURI)858 SessionHistoryEntry::GetBaseURI(nsIURI** aBaseURI) {
859   nsCOMPtr<nsIURI> baseURI = mInfo->mBaseURI;
860   baseURI.forget(aBaseURI);
861   return NS_OK;
862 }
863 
864 NS_IMETHODIMP
SetBaseURI(nsIURI * aBaseURI)865 SessionHistoryEntry::SetBaseURI(nsIURI* aBaseURI) {
866   mInfo->mBaseURI = aBaseURI;
867   return NS_OK;
868 }
869 
870 NS_IMETHODIMP
GetScrollRestorationIsManual(bool * aScrollRestorationIsManual)871 SessionHistoryEntry::GetScrollRestorationIsManual(
872     bool* aScrollRestorationIsManual) {
873   *aScrollRestorationIsManual = mInfo->mScrollRestorationIsManual;
874   return NS_OK;
875 }
876 
877 NS_IMETHODIMP
SetScrollRestorationIsManual(bool aScrollRestorationIsManual)878 SessionHistoryEntry::SetScrollRestorationIsManual(
879     bool aScrollRestorationIsManual) {
880   mInfo->mScrollRestorationIsManual = aScrollRestorationIsManual;
881   return NS_OK;
882 }
883 
884 NS_IMETHODIMP
GetLoadedInThisProcess(bool * aLoadedInThisProcess)885 SessionHistoryEntry::GetLoadedInThisProcess(bool* aLoadedInThisProcess) {
886   // FIXME
887   //*aLoadedInThisProcess = mInfo->mLoadedInThisProcess;
888   return NS_OK;
889 }
890 
891 NS_IMETHODIMP
GetShistory(nsISHistory ** aShistory)892 SessionHistoryEntry::GetShistory(nsISHistory** aShistory) {
893   nsCOMPtr<nsISHistory> sHistory = do_QueryReferent(SharedInfo()->mSHistory);
894   sHistory.forget(aShistory);
895   return NS_OK;
896 }
897 
898 NS_IMETHODIMP
SetShistory(nsISHistory * aShistory)899 SessionHistoryEntry::SetShistory(nsISHistory* aShistory) {
900   nsWeakPtr shistory = do_GetWeakReference(aShistory);
901   // mSHistory can not be changed once it's set
902   MOZ_ASSERT(!SharedInfo()->mSHistory || (SharedInfo()->mSHistory == shistory));
903   SharedInfo()->mSHistory = shistory;
904   return NS_OK;
905 }
906 
907 NS_IMETHODIMP
GetLastTouched(uint32_t * aLastTouched)908 SessionHistoryEntry::GetLastTouched(uint32_t* aLastTouched) {
909   *aLastTouched = SharedInfo()->mLastTouched;
910   return NS_OK;
911 }
912 
913 NS_IMETHODIMP
SetLastTouched(uint32_t aLastTouched)914 SessionHistoryEntry::SetLastTouched(uint32_t aLastTouched) {
915   SharedInfo()->mLastTouched = aLastTouched;
916   return NS_OK;
917 }
918 
919 NS_IMETHODIMP
GetChildCount(int32_t * aChildCount)920 SessionHistoryEntry::GetChildCount(int32_t* aChildCount) {
921   *aChildCount = mChildren.Length();
922   return NS_OK;
923 }
924 
925 NS_IMETHODIMP
GetPersist(bool * aPersist)926 SessionHistoryEntry::GetPersist(bool* aPersist) {
927   *aPersist = mInfo->mPersist;
928   return NS_OK;
929 }
930 
931 NS_IMETHODIMP
SetPersist(bool aPersist)932 SessionHistoryEntry::SetPersist(bool aPersist) {
933   mInfo->mPersist = aPersist;
934   return NS_OK;
935 }
936 
937 NS_IMETHODIMP
GetScrollPosition(int32_t * aX,int32_t * aY)938 SessionHistoryEntry::GetScrollPosition(int32_t* aX, int32_t* aY) {
939   *aX = mInfo->mScrollPositionX;
940   *aY = mInfo->mScrollPositionY;
941   return NS_OK;
942 }
943 
944 NS_IMETHODIMP
SetScrollPosition(int32_t aX,int32_t aY)945 SessionHistoryEntry::SetScrollPosition(int32_t aX, int32_t aY) {
946   mInfo->mScrollPositionX = aX;
947   mInfo->mScrollPositionY = aY;
948   return NS_OK;
949 }
950 
NS_IMETHODIMP_(void)951 NS_IMETHODIMP_(void)
952 SessionHistoryEntry::GetViewerBounds(nsIntRect& bounds) {
953   bounds = SharedInfo()->mViewerBounds;
954 }
955 
NS_IMETHODIMP_(void)956 NS_IMETHODIMP_(void)
957 SessionHistoryEntry::SetViewerBounds(const nsIntRect& bounds) {
958   SharedInfo()->mViewerBounds = bounds;
959 }
960 
NS_IMETHODIMP_(void)961 NS_IMETHODIMP_(void)
962 SessionHistoryEntry::AddChildShell(nsIDocShellTreeItem* shell) {
963   MOZ_CRASH("This lives in the child process");
964 }
965 
966 NS_IMETHODIMP
ChildShellAt(int32_t index,nsIDocShellTreeItem ** _retval)967 SessionHistoryEntry::ChildShellAt(int32_t index,
968                                   nsIDocShellTreeItem** _retval) {
969   MOZ_CRASH("This lives in the child process");
970   return NS_ERROR_FAILURE;
971 }
972 
NS_IMETHODIMP_(void)973 NS_IMETHODIMP_(void)
974 SessionHistoryEntry::ClearChildShells() {
975   MOZ_CRASH("This lives in the child process");
976 }
977 
NS_IMETHODIMP_(void)978 NS_IMETHODIMP_(void)
979 SessionHistoryEntry::SyncPresentationState() {
980   MOZ_CRASH("This lives in the child process");
981 }
982 
983 NS_IMETHODIMP
InitLayoutHistoryState(nsILayoutHistoryState ** aLayoutHistoryState)984 SessionHistoryEntry::InitLayoutHistoryState(
985     nsILayoutHistoryState** aLayoutHistoryState) {
986   if (!SharedInfo()->mLayoutHistoryState) {
987     nsCOMPtr<nsILayoutHistoryState> historyState;
988     historyState = NS_NewLayoutHistoryState();
989     SetLayoutHistoryState(historyState);
990   }
991 
992   return GetLayoutHistoryState(aLayoutHistoryState);
993 }
994 
995 NS_IMETHODIMP
Create(nsIURI * aURI,const nsAString & aTitle,nsIInputStream * aInputStream,uint32_t aCacheKey,const nsACString & aContentType,nsIPrincipal * aTriggeringPrincipal,nsIPrincipal * aPrincipalToInherit,nsIPrincipal * aPartitionedPrincipalToInherit,nsIContentSecurityPolicy * aCsp,const nsID & aDocshellID,bool aDynamicCreation,nsIURI * aOriginalURI,nsIURI * aResultPrincipalURI,bool aLoadReplace,nsIReferrerInfo * aReferrerInfo,const nsAString & aSrcdoc,bool aSrcdocEntry,nsIURI * aBaseURI,bool aSaveLayoutState,bool aExpired,bool aUserActivation)996 SessionHistoryEntry::Create(
997     nsIURI* aURI, const nsAString& aTitle, nsIInputStream* aInputStream,
998     uint32_t aCacheKey, const nsACString& aContentType,
999     nsIPrincipal* aTriggeringPrincipal, nsIPrincipal* aPrincipalToInherit,
1000     nsIPrincipal* aPartitionedPrincipalToInherit,
1001     nsIContentSecurityPolicy* aCsp, const nsID& aDocshellID,
1002     bool aDynamicCreation, nsIURI* aOriginalURI, nsIURI* aResultPrincipalURI,
1003     bool aLoadReplace, nsIReferrerInfo* aReferrerInfo, const nsAString& aSrcdoc,
1004     bool aSrcdocEntry, nsIURI* aBaseURI, bool aSaveLayoutState, bool aExpired,
1005     bool aUserActivation) {
1006   MOZ_CRASH("Might need to implement this");
1007   return NS_ERROR_NOT_IMPLEMENTED;
1008 }
1009 
1010 NS_IMETHODIMP
Clone(nsISHEntry ** aEntry)1011 SessionHistoryEntry::Clone(nsISHEntry** aEntry) {
1012   RefPtr<SessionHistoryEntry> entry = new SessionHistoryEntry(*this);
1013 
1014   // These are not copied for some reason, we're not sure why.
1015   entry->mInfo->mLoadType = 0;
1016   entry->mInfo->mScrollPositionX = 0;
1017   entry->mInfo->mScrollPositionY = 0;
1018   entry->mInfo->mScrollRestorationIsManual = false;
1019 
1020   entry->mInfo->mHasUserInteraction = false;
1021 
1022   entry.forget(aEntry);
1023 
1024   return NS_OK;
1025 }
1026 
NS_IMETHODIMP_(nsDocShellEditorData *)1027 NS_IMETHODIMP_(nsDocShellEditorData*)
1028 SessionHistoryEntry::ForgetEditorData() {
1029   MOZ_CRASH("This lives in the child process");
1030   return nullptr;
1031 }
1032 
NS_IMETHODIMP_(void)1033 NS_IMETHODIMP_(void)
1034 SessionHistoryEntry::SetEditorData(nsDocShellEditorData* aData) {
1035   NS_WARNING("This lives in the child process");
1036 }
1037 
NS_IMETHODIMP_(bool)1038 NS_IMETHODIMP_(bool)
1039 SessionHistoryEntry::HasDetachedEditor() {
1040   NS_WARNING("This lives in the child process");
1041   return false;
1042 }
1043 
NS_IMETHODIMP_(bool)1044 NS_IMETHODIMP_(bool)
1045 SessionHistoryEntry::IsDynamicallyAdded() {
1046   return SharedInfo()->mDynamicallyCreated;
1047 }
1048 
SetIsDynamicallyAdded(bool aDynamic)1049 void SessionHistoryEntry::SetIsDynamicallyAdded(bool aDynamic) {
1050   MOZ_ASSERT_IF(SharedInfo()->mDynamicallyCreated, aDynamic);
1051   SharedInfo()->mDynamicallyCreated = aDynamic;
1052 }
1053 
1054 NS_IMETHODIMP
HasDynamicallyAddedChild(bool * aHasDynamicallyAddedChild)1055 SessionHistoryEntry::HasDynamicallyAddedChild(bool* aHasDynamicallyAddedChild) {
1056   for (const auto& child : mChildren) {
1057     if (child && child->IsDynamicallyAdded()) {
1058       *aHasDynamicallyAddedChild = true;
1059       return NS_OK;
1060     }
1061   }
1062   *aHasDynamicallyAddedChild = false;
1063   return NS_OK;
1064 }
1065 
NS_IMETHODIMP_(bool)1066 NS_IMETHODIMP_(bool)
1067 SessionHistoryEntry::HasBFCacheEntry(SHEntrySharedParentState* aEntry) {
1068   return SharedInfo() == aEntry;
1069 }
1070 
1071 NS_IMETHODIMP
AdoptBFCacheEntry(nsISHEntry * aEntry)1072 SessionHistoryEntry::AdoptBFCacheEntry(nsISHEntry* aEntry) {
1073   nsCOMPtr<SessionHistoryEntry> she = do_QueryInterface(aEntry);
1074   NS_ENSURE_STATE(she && she->mInfo->mSharedState.Get());
1075 
1076   mInfo->mSharedState =
1077       static_cast<SessionHistoryEntry*>(aEntry)->mInfo->mSharedState;
1078 
1079   return NS_OK;
1080 }
1081 
1082 NS_IMETHODIMP
AbandonBFCacheEntry()1083 SessionHistoryEntry::AbandonBFCacheEntry() {
1084   MOZ_CRASH("This lives in the child process");
1085   return NS_ERROR_FAILURE;
1086 }
1087 
1088 NS_IMETHODIMP
SharesDocumentWith(nsISHEntry * aEntry,bool * aSharesDocumentWith)1089 SessionHistoryEntry::SharesDocumentWith(nsISHEntry* aEntry,
1090                                         bool* aSharesDocumentWith) {
1091   SessionHistoryEntry* entry = static_cast<SessionHistoryEntry*>(aEntry);
1092 
1093   MOZ_ASSERT_IF(entry->SharedInfo() != SharedInfo(),
1094                 entry->SharedInfo()->GetId() != SharedInfo()->GetId());
1095 
1096   *aSharesDocumentWith = entry->SharedInfo() == SharedInfo();
1097   return NS_OK;
1098 }
1099 
1100 NS_IMETHODIMP
SetLoadTypeAsHistory()1101 SessionHistoryEntry::SetLoadTypeAsHistory() {
1102   mInfo->mLoadType = LOAD_HISTORY;
1103   return NS_OK;
1104 }
1105 
1106 NS_IMETHODIMP
AddChild(nsISHEntry * aChild,int32_t aOffset,bool aUseRemoteSubframes)1107 SessionHistoryEntry::AddChild(nsISHEntry* aChild, int32_t aOffset,
1108                               bool aUseRemoteSubframes) {
1109   nsCOMPtr<SessionHistoryEntry> child = do_QueryInterface(aChild);
1110   MOZ_ASSERT_IF(aChild, child);
1111   AddChild(child, aOffset, aUseRemoteSubframes);
1112 
1113   return NS_OK;
1114 }
1115 
AddChild(SessionHistoryEntry * aChild,int32_t aOffset,bool aUseRemoteSubframes)1116 void SessionHistoryEntry::AddChild(SessionHistoryEntry* aChild, int32_t aOffset,
1117                                    bool aUseRemoteSubframes) {
1118   if (aChild) {
1119     aChild->SetParent(this);
1120   }
1121 
1122   if (aOffset < 0) {
1123     mChildren.AppendElement(aChild);
1124     return;
1125   }
1126 
1127   //
1128   // Bug 52670: Ensure children are added in order.
1129   //
1130   //  Later frames in the child list may load faster and get appended
1131   //  before earlier frames, causing session history to be scrambled.
1132   //  By growing the list here, they are added to the right position.
1133 
1134   int32_t length = mChildren.Length();
1135 
1136   //  Assert that aOffset will not be so high as to grow us a lot.
1137   NS_ASSERTION(aOffset < length + 1023, "Large frames array!\n");
1138 
1139   // If the new child is dynamically added, try to add it to aOffset, but if
1140   // there are non-dynamically added children, the child must be after those.
1141   if (aChild && aChild->IsDynamicallyAdded()) {
1142     int32_t lastNonDyn = aOffset - 1;
1143     for (int32_t i = aOffset; i < length; ++i) {
1144       SessionHistoryEntry* entry = mChildren[i];
1145       if (entry) {
1146         if (entry->IsDynamicallyAdded()) {
1147           break;
1148         }
1149 
1150         lastNonDyn = i;
1151       }
1152     }
1153 
1154     // If aOffset is larger than Length(), we must first truncate the array.
1155     if (aOffset > length) {
1156       mChildren.SetLength(aOffset);
1157     }
1158 
1159     mChildren.InsertElementAt(lastNonDyn + 1, aChild);
1160 
1161     return;
1162   }
1163 
1164   // If the new child isn't dynamically added, it should be set to aOffset.
1165   // If there are dynamically added children before that, those must be moved
1166   // to be after aOffset.
1167   if (length > 0) {
1168     int32_t start = std::min(length - 1, aOffset);
1169     int32_t dynEntryIndex = -1;
1170     DebugOnly<SessionHistoryEntry*> dynEntry = nullptr;
1171     for (int32_t i = start; i >= 0; --i) {
1172       SessionHistoryEntry* entry = mChildren[i];
1173       if (entry) {
1174         if (!entry->IsDynamicallyAdded()) {
1175           break;
1176         }
1177 
1178         dynEntryIndex = i;
1179         dynEntry = entry;
1180       }
1181     }
1182 
1183     if (dynEntryIndex >= 0) {
1184       mChildren.InsertElementsAt(dynEntryIndex, aOffset - dynEntryIndex + 1);
1185       NS_ASSERTION(mChildren[aOffset + 1] == dynEntry, "Whaat?");
1186     }
1187   }
1188 
1189   // Make sure there isn't anything at aOffset.
1190   if ((uint32_t)aOffset < mChildren.Length()) {
1191     SessionHistoryEntry* oldChild = mChildren[aOffset];
1192     if (oldChild && oldChild != aChild) {
1193       // Under Fission, this can happen when a network-created iframe starts
1194       // out in-process, moves out-of-process, and then switches back. At that
1195       // point, we'll create a new network-created DocShell at the same index
1196       // where we already have an entry for the original network-created
1197       // DocShell.
1198       //
1199       // This should ideally stop being an issue once the Fission-aware
1200       // session history rewrite is complete.
1201       NS_ASSERTION(
1202           aUseRemoteSubframes || NS_IsAboutBlank(oldChild->Info().GetURI()),
1203           "Adding a child where we already have a child? This may misbehave");
1204       oldChild->SetParent(nullptr);
1205     }
1206   } else {
1207     mChildren.SetLength(aOffset + 1);
1208   }
1209 
1210   mChildren.ReplaceElementAt(aOffset, aChild);
1211 }
1212 
1213 NS_IMETHODIMP
RemoveChild(nsISHEntry * aChild)1214 SessionHistoryEntry::RemoveChild(nsISHEntry* aChild) {
1215   NS_ENSURE_TRUE(aChild, NS_ERROR_FAILURE);
1216 
1217   nsCOMPtr<SessionHistoryEntry> child = do_QueryInterface(aChild);
1218   MOZ_ASSERT(child);
1219   RemoveChild(child);
1220 
1221   return NS_OK;
1222 }
1223 
RemoveChild(SessionHistoryEntry * aChild)1224 void SessionHistoryEntry::RemoveChild(SessionHistoryEntry* aChild) {
1225   bool childRemoved = false;
1226   if (aChild->IsDynamicallyAdded()) {
1227     childRemoved = mChildren.RemoveElement(aChild);
1228   } else {
1229     int32_t index = mChildren.IndexOf(aChild);
1230     if (index >= 0) {
1231       // Other alive non-dynamic child docshells still keep mChildOffset,
1232       // so we don't want to change the indices here.
1233       mChildren.ReplaceElementAt(index, nullptr);
1234       childRemoved = true;
1235     }
1236   }
1237 
1238   if (childRemoved) {
1239     aChild->SetParent(nullptr);
1240 
1241     // reduce the child count, i.e. remove empty children at the end
1242     for (int32_t i = mChildren.Length() - 1; i >= 0 && !mChildren[i]; --i) {
1243       mChildren.RemoveElementAt(i);
1244     }
1245   }
1246 }
1247 
1248 NS_IMETHODIMP
GetChildAt(int32_t aIndex,nsISHEntry ** aChild)1249 SessionHistoryEntry::GetChildAt(int32_t aIndex, nsISHEntry** aChild) {
1250   nsCOMPtr<nsISHEntry> child = mChildren.SafeElementAt(aIndex);
1251   child.forget(aChild);
1252   return NS_OK;
1253 }
1254 
NS_IMETHODIMP_(void)1255 NS_IMETHODIMP_(void)
1256 SessionHistoryEntry::GetChildSHEntryIfHasNoDynamicallyAddedChild(
1257     int32_t aChildOffset, nsISHEntry** aChild) {
1258   *aChild = nullptr;
1259 
1260   bool dynamicallyAddedChild = false;
1261   HasDynamicallyAddedChild(&dynamicallyAddedChild);
1262   if (dynamicallyAddedChild) {
1263     return;
1264   }
1265 
1266   // If the user did a shift-reload on this frameset page,
1267   // we don't want to load the subframes from history.
1268   if (IsForceReloadType(mInfo->mLoadType) || mInfo->mLoadType == LOAD_REFRESH) {
1269     return;
1270   }
1271 
1272   /* Before looking for the subframe's url, check
1273    * the expiration status of the parent. If the parent
1274    * has expired from cache, then subframes will not be
1275    * loaded from history in certain situations.
1276    * If the user pressed reload and the parent frame has expired
1277    *  from cache, we do not want to load the child frame from history.
1278    */
1279   if (SharedInfo()->mExpired && (mInfo->mLoadType == LOAD_RELOAD_NORMAL)) {
1280     // The parent has expired. Return null.
1281     *aChild = nullptr;
1282     return;
1283   }
1284   // Get the child subframe from session history.
1285   GetChildAt(aChildOffset, aChild);
1286   if (*aChild) {
1287     // Set the parent's Load Type on the child
1288     (*aChild)->SetLoadType(mInfo->mLoadType);
1289   }
1290 }
1291 
1292 NS_IMETHODIMP
ReplaceChild(nsISHEntry * aNewChild)1293 SessionHistoryEntry::ReplaceChild(nsISHEntry* aNewChild) {
1294   NS_ENSURE_STATE(aNewChild);
1295 
1296   nsCOMPtr<SessionHistoryEntry> newChild = do_QueryInterface(aNewChild);
1297   MOZ_ASSERT(newChild);
1298   return ReplaceChild(newChild) ? NS_OK : NS_ERROR_FAILURE;
1299 }
1300 
ReplaceChild(SessionHistoryEntry * aNewChild)1301 bool SessionHistoryEntry::ReplaceChild(SessionHistoryEntry* aNewChild) {
1302   const nsID& docshellID = aNewChild->DocshellID();
1303 
1304   for (uint32_t i = 0; i < mChildren.Length(); ++i) {
1305     if (mChildren[i] && docshellID == mChildren[i]->DocshellID()) {
1306       mChildren[i]->SetParent(nullptr);
1307       mChildren.ReplaceElementAt(i, aNewChild);
1308       aNewChild->SetParent(this);
1309 
1310       return true;
1311     }
1312   }
1313 
1314   return false;
1315 }
1316 
NS_IMETHODIMP_(void)1317 NS_IMETHODIMP_(void)
1318 SessionHistoryEntry::ClearEntry() {
1319   int32_t childCount = GetChildCount();
1320   // Remove all children of this entry
1321   for (int32_t i = childCount; i > 0; --i) {
1322     nsCOMPtr<nsISHEntry> child;
1323     GetChildAt(i - 1, getter_AddRefs(child));
1324     RemoveChild(child);
1325   }
1326 }
1327 
1328 NS_IMETHODIMP
CreateLoadInfo(nsDocShellLoadState ** aLoadState)1329 SessionHistoryEntry::CreateLoadInfo(nsDocShellLoadState** aLoadState) {
1330   NS_WARNING("We shouldn't be calling this!");
1331   return NS_OK;
1332 }
1333 
1334 NS_IMETHODIMP
GetBfcacheID(uint64_t * aBfcacheID)1335 SessionHistoryEntry::GetBfcacheID(uint64_t* aBfcacheID) {
1336   *aBfcacheID = SharedInfo()->mId;
1337   return NS_OK;
1338 }
1339 
NS_IMETHODIMP_(void)1340 NS_IMETHODIMP_(void)
1341 SessionHistoryEntry::SyncTreesForSubframeNavigation(
1342     nsISHEntry* aEntry, mozilla::dom::BrowsingContext* aTopBC,
1343     mozilla::dom::BrowsingContext* aIgnoreBC) {
1344   // XXX Keep this in sync with nsSHEntry::SyncTreesForSubframeNavigation.
1345   //
1346   // We need to sync up the browsing context and session history trees for
1347   // subframe navigation.  If the load was in a subframe, we forward up to
1348   // the top browsing context, which will then recursively sync up all browsing
1349   // contexts to their corresponding entries in the new session history tree. If
1350   // we don't do this, then we can cache a content viewer on the wrong cloned
1351   // entry, and subsequently restore it at the wrong time.
1352   nsCOMPtr<nsISHEntry> newRootEntry = nsSHistory::GetRootSHEntry(aEntry);
1353   if (newRootEntry) {
1354     // newRootEntry is now the new root entry.
1355     // Find the old root entry as well.
1356 
1357     // Need a strong ref. on |oldRootEntry| so it isn't destroyed when
1358     // SetChildHistoryEntry() does SwapHistoryEntries() (bug 304639).
1359     nsCOMPtr<nsISHEntry> oldRootEntry = nsSHistory::GetRootSHEntry(this);
1360 
1361     if (oldRootEntry) {
1362       nsSHistory::SwapEntriesData data = {aIgnoreBC, newRootEntry, nullptr};
1363       nsSHistory::SetChildHistoryEntry(oldRootEntry, aTopBC, 0, &data);
1364     }
1365   }
1366 }
1367 
ReplaceWith(const SessionHistoryEntry & aSource)1368 void SessionHistoryEntry::ReplaceWith(const SessionHistoryEntry& aSource) {
1369   mInfo = MakeUnique<SessionHistoryInfo>(*aSource.mInfo);
1370   mChildren.Clear();
1371 }
1372 
SharedInfo() const1373 SHEntrySharedParentState* SessionHistoryEntry::SharedInfo() const {
1374   return static_cast<SHEntrySharedParentState*>(mInfo->mSharedState.Get());
1375 }
1376 
SetFrameLoader(nsFrameLoader * aFrameLoader)1377 void SessionHistoryEntry::SetFrameLoader(nsFrameLoader* aFrameLoader) {
1378   MOZ_ASSERT_IF(aFrameLoader, !SharedInfo()->mFrameLoader);
1379   // If the pref is disabled, we still allow evicting the existing entries.
1380   MOZ_RELEASE_ASSERT(!aFrameLoader || mozilla::BFCacheInParent());
1381   SharedInfo()->SetFrameLoader(aFrameLoader);
1382   if (aFrameLoader) {
1383     if (BrowserParent* bp = aFrameLoader->GetBrowserParent()) {
1384       bp->Deactivated();
1385     }
1386 
1387     // When a new frameloader is stored, try to evict some older
1388     // frameloaders. Non-SHIP session history has a similar call in
1389     // nsDocumentViewer::Show.
1390     nsCOMPtr<nsISHistory> shistory;
1391     GetShistory(getter_AddRefs(shistory));
1392     if (shistory) {
1393       int32_t index = 0;
1394       shistory->GetIndex(&index);
1395       shistory->EvictOutOfRangeContentViewers(index);
1396     }
1397   }
1398 }
1399 
GetFrameLoader()1400 nsFrameLoader* SessionHistoryEntry::GetFrameLoader() {
1401   return SharedInfo()->mFrameLoader;
1402 }
1403 
SetInfo(SessionHistoryInfo * aInfo)1404 void SessionHistoryEntry::SetInfo(SessionHistoryInfo* aInfo) {
1405   // FIXME Assert that we're not changing shared state!
1406   mInfo = MakeUnique<SessionHistoryInfo>(*aInfo);
1407 }
1408 
1409 }  // namespace dom
1410 
1411 namespace ipc {
1412 
Write(IPC::Message * aMsg,IProtocol * aActor,const dom::SessionHistoryInfo & aParam)1413 void IPDLParamTraits<dom::SessionHistoryInfo>::Write(
1414     IPC::Message* aMsg, IProtocol* aActor,
1415     const dom::SessionHistoryInfo& aParam) {
1416   Maybe<Tuple<uint32_t, dom::ClonedMessageData>> stateData;
1417   if (aParam.mStateData) {
1418     stateData.emplace();
1419     uint32_t version;
1420     NS_ENSURE_SUCCESS_VOID(aParam.mStateData->GetFormatVersion(&version));
1421     Get<0>(*stateData) = version;
1422 
1423     IToplevelProtocol* topLevel = aActor->ToplevelProtocol();
1424     MOZ_RELEASE_ASSERT(topLevel->GetProtocolId() == PContentMsgStart);
1425     if (topLevel->GetSide() == ChildSide) {
1426       auto* contentChild = static_cast<dom::ContentChild*>(topLevel);
1427       if (NS_WARN_IF(!aParam.mStateData->BuildClonedMessageDataForChild(
1428               contentChild, Get<1>(*stateData)))) {
1429         return;
1430       }
1431     } else {
1432       auto* contentParent = static_cast<dom::ContentParent*>(topLevel);
1433       if (NS_WARN_IF(!aParam.mStateData->BuildClonedMessageDataForParent(
1434               contentParent, Get<1>(*stateData)))) {
1435         return;
1436       }
1437     }
1438   }
1439 
1440   WriteIPDLParam(aMsg, aActor, aParam.mURI);
1441   WriteIPDLParam(aMsg, aActor, aParam.mOriginalURI);
1442   WriteIPDLParam(aMsg, aActor, aParam.mResultPrincipalURI);
1443   WriteIPDLParam(aMsg, aActor, aParam.mReferrerInfo);
1444   WriteIPDLParam(aMsg, aActor, aParam.mTitle);
1445   WriteIPDLParam(aMsg, aActor, aParam.mName);
1446   WriteIPDLParam(aMsg, aActor, aParam.mPostData);
1447   WriteIPDLParam(aMsg, aActor, aParam.mLoadType);
1448   WriteIPDLParam(aMsg, aActor, aParam.mScrollPositionX);
1449   WriteIPDLParam(aMsg, aActor, aParam.mScrollPositionY);
1450   WriteIPDLParam(aMsg, aActor, stateData);
1451   WriteIPDLParam(aMsg, aActor, aParam.mSrcdocData);
1452   WriteIPDLParam(aMsg, aActor, aParam.mBaseURI);
1453   WriteIPDLParam(aMsg, aActor, aParam.mLoadReplace);
1454   WriteIPDLParam(aMsg, aActor, aParam.mURIWasModified);
1455   WriteIPDLParam(aMsg, aActor, aParam.mScrollRestorationIsManual);
1456   WriteIPDLParam(aMsg, aActor, aParam.mPersist);
1457   WriteIPDLParam(aMsg, aActor, aParam.mHasUserInteraction);
1458   WriteIPDLParam(aMsg, aActor, aParam.mHasUserActivation);
1459   WriteIPDLParam(aMsg, aActor, aParam.mSharedState.Get()->mId);
1460   WriteIPDLParam(aMsg, aActor, aParam.mSharedState.Get()->mTriggeringPrincipal);
1461   WriteIPDLParam(aMsg, aActor, aParam.mSharedState.Get()->mPrincipalToInherit);
1462   WriteIPDLParam(aMsg, aActor,
1463                  aParam.mSharedState.Get()->mPartitionedPrincipalToInherit);
1464   WriteIPDLParam(aMsg, aActor, aParam.mSharedState.Get()->mCsp);
1465   WriteIPDLParam(aMsg, aActor, aParam.mSharedState.Get()->mContentType);
1466   WriteIPDLParam(aMsg, aActor, aParam.mSharedState.Get()->mLayoutHistoryState);
1467   WriteIPDLParam(aMsg, aActor, aParam.mSharedState.Get()->mCacheKey);
1468   WriteIPDLParam(aMsg, aActor, aParam.mSharedState.Get()->mIsFrameNavigation);
1469 }
1470 
Read(const IPC::Message * aMsg,PickleIterator * aIter,IProtocol * aActor,dom::SessionHistoryInfo * aResult)1471 bool IPDLParamTraits<dom::SessionHistoryInfo>::Read(
1472     const IPC::Message* aMsg, PickleIterator* aIter, IProtocol* aActor,
1473     dom::SessionHistoryInfo* aResult) {
1474   Maybe<Tuple<uint32_t, dom::ClonedMessageData>> stateData;
1475   uint64_t sharedId;
1476   if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mURI) ||
1477       !ReadIPDLParam(aMsg, aIter, aActor, &aResult->mOriginalURI) ||
1478       !ReadIPDLParam(aMsg, aIter, aActor, &aResult->mResultPrincipalURI) ||
1479       !ReadIPDLParam(aMsg, aIter, aActor, &aResult->mReferrerInfo) ||
1480       !ReadIPDLParam(aMsg, aIter, aActor, &aResult->mTitle) ||
1481       !ReadIPDLParam(aMsg, aIter, aActor, &aResult->mName) ||
1482       !ReadIPDLParam(aMsg, aIter, aActor, &aResult->mPostData) ||
1483       !ReadIPDLParam(aMsg, aIter, aActor, &aResult->mLoadType) ||
1484       !ReadIPDLParam(aMsg, aIter, aActor, &aResult->mScrollPositionX) ||
1485       !ReadIPDLParam(aMsg, aIter, aActor, &aResult->mScrollPositionY) ||
1486       !ReadIPDLParam(aMsg, aIter, aActor, &stateData) ||
1487       !ReadIPDLParam(aMsg, aIter, aActor, &aResult->mSrcdocData) ||
1488       !ReadIPDLParam(aMsg, aIter, aActor, &aResult->mBaseURI) ||
1489       !ReadIPDLParam(aMsg, aIter, aActor, &aResult->mLoadReplace) ||
1490       !ReadIPDLParam(aMsg, aIter, aActor, &aResult->mURIWasModified) ||
1491       !ReadIPDLParam(aMsg, aIter, aActor,
1492                      &aResult->mScrollRestorationIsManual) ||
1493       !ReadIPDLParam(aMsg, aIter, aActor, &aResult->mPersist) ||
1494       !ReadIPDLParam(aMsg, aIter, aActor, &aResult->mHasUserInteraction) ||
1495       !ReadIPDLParam(aMsg, aIter, aActor, &aResult->mHasUserActivation) ||
1496       !ReadIPDLParam(aMsg, aIter, aActor, &sharedId)) {
1497     aActor->FatalError("Error reading fields for SessionHistoryInfo");
1498     return false;
1499   }
1500 
1501   nsCOMPtr<nsIPrincipal> triggeringPrincipal;
1502   nsCOMPtr<nsIPrincipal> principalToInherit;
1503   nsCOMPtr<nsIPrincipal> partitionedPrincipalToInherit;
1504   nsCOMPtr<nsIContentSecurityPolicy> csp;
1505   nsCString contentType;
1506   if (!ReadIPDLParam(aMsg, aIter, aActor, &triggeringPrincipal) ||
1507       !ReadIPDLParam(aMsg, aIter, aActor, &principalToInherit) ||
1508       !ReadIPDLParam(aMsg, aIter, aActor, &partitionedPrincipalToInherit) ||
1509       !ReadIPDLParam(aMsg, aIter, aActor, &csp) ||
1510       !ReadIPDLParam(aMsg, aIter, aActor, &contentType)) {
1511     aActor->FatalError("Error reading fields for SessionHistoryInfo");
1512     return false;
1513   }
1514 
1515   dom::SHEntrySharedParentState* sharedState = nullptr;
1516   if (XRE_IsParentProcess()) {
1517     sharedState = dom::SHEntrySharedParentState::Lookup(sharedId);
1518   }
1519 
1520   if (sharedState) {
1521     aResult->mSharedState.Set(sharedState);
1522 
1523     MOZ_ASSERT(triggeringPrincipal
1524                    ? triggeringPrincipal->Equals(
1525                          aResult->mSharedState.Get()->mTriggeringPrincipal)
1526                    : !aResult->mSharedState.Get()->mTriggeringPrincipal,
1527                "We don't expect this to change!");
1528     MOZ_ASSERT(principalToInherit
1529                    ? principalToInherit->Equals(
1530                          aResult->mSharedState.Get()->mPrincipalToInherit)
1531                    : !aResult->mSharedState.Get()->mPrincipalToInherit,
1532                "We don't expect this to change!");
1533     MOZ_ASSERT(
1534         partitionedPrincipalToInherit
1535             ? partitionedPrincipalToInherit->Equals(
1536                   aResult->mSharedState.Get()->mPartitionedPrincipalToInherit)
1537             : !aResult->mSharedState.Get()->mPartitionedPrincipalToInherit,
1538         "We don't expect this to change!");
1539     MOZ_ASSERT(
1540         csp ? nsCSPContext::Equals(csp, aResult->mSharedState.Get()->mCsp)
1541             : !aResult->mSharedState.Get()->mCsp,
1542         "We don't expect this to change!");
1543     MOZ_ASSERT(contentType.Equals(aResult->mSharedState.Get()->mContentType),
1544                "We don't expect this to change!");
1545   } else {
1546     aResult->mSharedState.ChangeId(sharedId);
1547     aResult->mSharedState.Get()->mTriggeringPrincipal =
1548         triggeringPrincipal.forget();
1549     aResult->mSharedState.Get()->mPrincipalToInherit =
1550         principalToInherit.forget();
1551     aResult->mSharedState.Get()->mPartitionedPrincipalToInherit =
1552         partitionedPrincipalToInherit.forget();
1553     aResult->mSharedState.Get()->mCsp = csp.forget();
1554     aResult->mSharedState.Get()->mContentType = contentType;
1555   }
1556 
1557   if (!ReadIPDLParam(aMsg, aIter, aActor,
1558                      &aResult->mSharedState.Get()->mLayoutHistoryState) ||
1559       !ReadIPDLParam(aMsg, aIter, aActor,
1560                      &aResult->mSharedState.Get()->mCacheKey) ||
1561       !ReadIPDLParam(aMsg, aIter, aActor,
1562                      &aResult->mSharedState.Get()->mIsFrameNavigation)) {
1563     aActor->FatalError("Error reading fields for SessionHistoryInfo");
1564     return false;
1565   }
1566 
1567   if (stateData.isSome()) {
1568     uint32_t version = Get<0>(*stateData);
1569     aResult->mStateData = new nsStructuredCloneContainer(version);
1570     if (aActor->GetSide() == ChildSide) {
1571       aResult->mStateData->StealFromClonedMessageDataForChild(
1572           Get<1>(*stateData));
1573     } else {
1574       aResult->mStateData->StealFromClonedMessageDataForParent(
1575           Get<1>(*stateData));
1576     }
1577   }
1578   MOZ_ASSERT_IF(stateData.isNothing(), !aResult->mStateData);
1579   return true;
1580 }
1581 
Write(IPC::Message * aMsg,IProtocol * aActor,const dom::LoadingSessionHistoryInfo & aParam)1582 void IPDLParamTraits<dom::LoadingSessionHistoryInfo>::Write(
1583     IPC::Message* aMsg, IProtocol* aActor,
1584     const dom::LoadingSessionHistoryInfo& aParam) {
1585   WriteIPDLParam(aMsg, aActor, aParam.mInfo);
1586   WriteIPDLParam(aMsg, aActor, aParam.mLoadId);
1587   WriteIPDLParam(aMsg, aActor, aParam.mLoadIsFromSessionHistory);
1588   WriteIPDLParam(aMsg, aActor, aParam.mRequestedIndex);
1589   WriteIPDLParam(aMsg, aActor, aParam.mSessionHistoryLength);
1590   WriteIPDLParam(aMsg, aActor, aParam.mLoadingCurrentActiveEntry);
1591   WriteIPDLParam(aMsg, aActor, aParam.mForceMaybeResetName);
1592 }
1593 
Read(const IPC::Message * aMsg,PickleIterator * aIter,IProtocol * aActor,dom::LoadingSessionHistoryInfo * aResult)1594 bool IPDLParamTraits<dom::LoadingSessionHistoryInfo>::Read(
1595     const IPC::Message* aMsg, PickleIterator* aIter, IProtocol* aActor,
1596     dom::LoadingSessionHistoryInfo* aResult) {
1597   if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mInfo) ||
1598       !ReadIPDLParam(aMsg, aIter, aActor, &aResult->mLoadId) ||
1599       !ReadIPDLParam(aMsg, aIter, aActor,
1600                      &aResult->mLoadIsFromSessionHistory) ||
1601       !ReadIPDLParam(aMsg, aIter, aActor, &aResult->mRequestedIndex) ||
1602       !ReadIPDLParam(aMsg, aIter, aActor, &aResult->mSessionHistoryLength) ||
1603       !ReadIPDLParam(aMsg, aIter, aActor,
1604                      &aResult->mLoadingCurrentActiveEntry) ||
1605       !ReadIPDLParam(aMsg, aIter, aActor, &aResult->mForceMaybeResetName)) {
1606     aActor->FatalError("Error reading fields for LoadingSessionHistoryInfo");
1607     return false;
1608   }
1609 
1610   return true;
1611 }
1612 
Write(IPC::Message * aMsg,IProtocol * aActor,nsILayoutHistoryState * aParam)1613 void IPDLParamTraits<nsILayoutHistoryState*>::Write(
1614     IPC::Message* aMsg, IProtocol* aActor, nsILayoutHistoryState* aParam) {
1615   if (aParam) {
1616     WriteIPDLParam(aMsg, aActor, true);
1617     bool scrollPositionOnly = false;
1618     nsTArray<nsCString> keys;
1619     nsTArray<mozilla::PresState> states;
1620     aParam->GetContents(&scrollPositionOnly, keys, states);
1621     WriteIPDLParam(aMsg, aActor, scrollPositionOnly);
1622     WriteIPDLParam(aMsg, aActor, keys);
1623     WriteIPDLParam(aMsg, aActor, states);
1624   } else {
1625     WriteIPDLParam(aMsg, aActor, false);
1626   }
1627 }
1628 
Read(const IPC::Message * aMsg,PickleIterator * aIter,IProtocol * aActor,RefPtr<nsILayoutHistoryState> * aResult)1629 bool IPDLParamTraits<nsILayoutHistoryState*>::Read(
1630     const IPC::Message* aMsg, PickleIterator* aIter, IProtocol* aActor,
1631     RefPtr<nsILayoutHistoryState>* aResult) {
1632   bool hasLayoutHistoryState = false;
1633   if (!ReadIPDLParam(aMsg, aIter, aActor, &hasLayoutHistoryState)) {
1634     aActor->FatalError("Error reading fields for nsILayoutHistoryState");
1635     return false;
1636   }
1637 
1638   if (hasLayoutHistoryState) {
1639     bool scrollPositionOnly = false;
1640     nsTArray<nsCString> keys;
1641     nsTArray<mozilla::PresState> states;
1642     if (!ReadIPDLParam(aMsg, aIter, aActor, &scrollPositionOnly) ||
1643         !ReadIPDLParam(aMsg, aIter, aActor, &keys) ||
1644         !ReadIPDLParam(aMsg, aIter, aActor, &states)) {
1645       aActor->FatalError("Error reading fields for nsILayoutHistoryState");
1646     }
1647 
1648     if (keys.Length() != states.Length()) {
1649       aActor->FatalError("Error reading fields for nsILayoutHistoryState");
1650       return false;
1651     }
1652 
1653     *aResult = NS_NewLayoutHistoryState();
1654     (*aResult)->SetScrollPositionOnly(scrollPositionOnly);
1655     for (uint32_t i = 0; i < keys.Length(); ++i) {
1656       PresState& state = states[i];
1657       UniquePtr<PresState> newState = MakeUnique<PresState>(state);
1658       (*aResult)->AddState(keys[i], std::move(newState));
1659     }
1660   }
1661   return true;
1662 }
1663 
1664 }  // namespace ipc
1665 
1666 }  // namespace mozilla
1667