Source code

Revision control

Other Tools

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 "nsSHEntry.h"
8
9
#include <algorithm>
10
11
#include "nsIContentSecurityPolicy.h"
12
#include "nsDocShellEditorData.h"
13
#include "nsDocShellLoadTypes.h"
14
#include "nsIContentViewer.h"
15
#include "nsIDocShellTreeItem.h"
16
#include "nsIInputStream.h"
17
#include "nsILayoutHistoryState.h"
18
#include "nsIStructuredCloneContainer.h"
19
#include "nsIURI.h"
20
#include "nsSHEntryShared.h"
21
#include "nsSHistory.h"
22
23
#include "mozilla/net/ReferrerPolicy.h"
24
#include "mozilla/Logging.h"
25
#include "nsIReferrerInfo.h"
26
27
extern mozilla::LazyLogModule gPageCacheLog;
28
29
namespace dom = mozilla::dom;
30
31
static uint32_t gEntryID = 0;
32
33
nsSHEntry::nsSHEntry()
34
: mShared(new nsSHEntryShared()),
35
mLoadType(0),
36
mID(gEntryID++),
37
mScrollPositionX(0),
38
mScrollPositionY(0),
39
mParent(nullptr),
40
mLoadReplace(false),
41
mURIWasModified(false),
42
mIsSrcdocEntry(false),
43
mScrollRestorationIsManual(false),
44
mLoadedInThisProcess(false),
45
mPersist(true) {}
46
47
nsSHEntry::nsSHEntry(const nsSHEntry& aOther)
48
: mShared(aOther.mShared),
49
mURI(aOther.mURI),
50
mOriginalURI(aOther.mOriginalURI),
51
mResultPrincipalURI(aOther.mResultPrincipalURI),
52
mReferrerInfo(aOther.mReferrerInfo),
53
mTitle(aOther.mTitle),
54
mPostData(aOther.mPostData),
55
mLoadType(0) // XXX why not copy?
56
,
57
mID(aOther.mID),
58
mScrollPositionX(0) // XXX why not copy?
59
,
60
mScrollPositionY(0) // XXX why not copy?
61
,
62
mParent(aOther.mParent),
63
mStateData(aOther.mStateData),
64
mSrcdocData(aOther.mSrcdocData),
65
mBaseURI(aOther.mBaseURI),
66
mLoadReplace(aOther.mLoadReplace),
67
mURIWasModified(aOther.mURIWasModified),
68
mIsSrcdocEntry(aOther.mIsSrcdocEntry),
69
mScrollRestorationIsManual(false),
70
mLoadedInThisProcess(aOther.mLoadedInThisProcess),
71
mPersist(aOther.mPersist) {}
72
73
nsSHEntry::~nsSHEntry() {
74
// Null out the mParent pointers on all our kids.
75
for (nsISHEntry* entry : mChildren) {
76
if (entry) {
77
entry->SetParent(nullptr);
78
}
79
}
80
}
81
82
NS_IMPL_ISUPPORTS(nsSHEntry, nsISHEntry)
83
84
NS_IMETHODIMP
85
nsSHEntry::SetScrollPosition(int32_t aX, int32_t aY) {
86
mScrollPositionX = aX;
87
mScrollPositionY = aY;
88
return NS_OK;
89
}
90
91
NS_IMETHODIMP
92
nsSHEntry::GetScrollPosition(int32_t* aX, int32_t* aY) {
93
*aX = mScrollPositionX;
94
*aY = mScrollPositionY;
95
return NS_OK;
96
}
97
98
NS_IMETHODIMP
99
nsSHEntry::GetURIWasModified(bool* aOut) {
100
*aOut = mURIWasModified;
101
return NS_OK;
102
}
103
104
NS_IMETHODIMP
105
nsSHEntry::SetURIWasModified(bool aIn) {
106
mURIWasModified = aIn;
107
return NS_OK;
108
}
109
110
NS_IMETHODIMP
111
nsSHEntry::GetURI(nsIURI** aURI) {
112
*aURI = mURI;
113
NS_IF_ADDREF(*aURI);
114
return NS_OK;
115
}
116
117
NS_IMETHODIMP
118
nsSHEntry::SetURI(nsIURI* aURI) {
119
mURI = aURI;
120
return NS_OK;
121
}
122
123
NS_IMETHODIMP
124
nsSHEntry::GetOriginalURI(nsIURI** aOriginalURI) {
125
*aOriginalURI = mOriginalURI;
126
NS_IF_ADDREF(*aOriginalURI);
127
return NS_OK;
128
}
129
130
NS_IMETHODIMP
131
nsSHEntry::SetOriginalURI(nsIURI* aOriginalURI) {
132
mOriginalURI = aOriginalURI;
133
return NS_OK;
134
}
135
136
NS_IMETHODIMP
137
nsSHEntry::GetResultPrincipalURI(nsIURI** aResultPrincipalURI) {
138
*aResultPrincipalURI = mResultPrincipalURI;
139
NS_IF_ADDREF(*aResultPrincipalURI);
140
return NS_OK;
141
}
142
143
NS_IMETHODIMP
144
nsSHEntry::SetResultPrincipalURI(nsIURI* aResultPrincipalURI) {
145
mResultPrincipalURI = aResultPrincipalURI;
146
return NS_OK;
147
}
148
149
NS_IMETHODIMP
150
nsSHEntry::GetLoadReplace(bool* aLoadReplace) {
151
*aLoadReplace = mLoadReplace;
152
return NS_OK;
153
}
154
155
NS_IMETHODIMP
156
nsSHEntry::SetLoadReplace(bool aLoadReplace) {
157
mLoadReplace = aLoadReplace;
158
return NS_OK;
159
}
160
161
NS_IMETHODIMP
162
nsSHEntry::GetReferrerInfo(nsIReferrerInfo** aReferrerInfo) {
163
*aReferrerInfo = mReferrerInfo;
164
NS_IF_ADDREF(*aReferrerInfo);
165
return NS_OK;
166
}
167
168
NS_IMETHODIMP
169
nsSHEntry::SetReferrerInfo(nsIReferrerInfo* aReferrerInfo) {
170
mReferrerInfo = aReferrerInfo;
171
return NS_OK;
172
}
173
174
NS_IMETHODIMP
175
nsSHEntry::SetContentViewer(nsIContentViewer* aViewer) {
176
return mShared->SetContentViewer(aViewer);
177
}
178
179
NS_IMETHODIMP
180
nsSHEntry::GetContentViewer(nsIContentViewer** aResult) {
181
*aResult = mShared->mContentViewer;
182
NS_IF_ADDREF(*aResult);
183
return NS_OK;
184
}
185
186
NS_IMETHODIMP
187
nsSHEntry::SetSticky(bool aSticky) {
188
mShared->mSticky = aSticky;
189
return NS_OK;
190
}
191
192
NS_IMETHODIMP
193
nsSHEntry::GetSticky(bool* aSticky) {
194
*aSticky = mShared->mSticky;
195
return NS_OK;
196
}
197
198
NS_IMETHODIMP
199
nsSHEntry::GetTitle(nsAString& aTitle) {
200
// Check for empty title...
201
if (mTitle.IsEmpty() && mURI) {
202
// Default title is the URL.
203
nsAutoCString spec;
204
if (NS_SUCCEEDED(mURI->GetSpec(spec))) {
205
AppendUTF8toUTF16(spec, mTitle);
206
}
207
}
208
209
aTitle = mTitle;
210
return NS_OK;
211
}
212
213
NS_IMETHODIMP
214
nsSHEntry::SetTitle(const nsAString& aTitle) {
215
mTitle = aTitle;
216
return NS_OK;
217
}
218
219
NS_IMETHODIMP
220
nsSHEntry::GetPostData(nsIInputStream** aResult) {
221
*aResult = mPostData;
222
NS_IF_ADDREF(*aResult);
223
return NS_OK;
224
}
225
226
NS_IMETHODIMP
227
nsSHEntry::SetPostData(nsIInputStream* aPostData) {
228
mPostData = aPostData;
229
return NS_OK;
230
}
231
232
NS_IMETHODIMP
233
nsSHEntry::GetLayoutHistoryState(nsILayoutHistoryState** aResult) {
234
*aResult = mShared->mLayoutHistoryState;
235
NS_IF_ADDREF(*aResult);
236
return NS_OK;
237
}
238
239
NS_IMETHODIMP
240
nsSHEntry::SetLayoutHistoryState(nsILayoutHistoryState* aState) {
241
mShared->mLayoutHistoryState = aState;
242
if (mShared->mLayoutHistoryState) {
243
mShared->mLayoutHistoryState->SetScrollPositionOnly(
244
!mShared->mSaveLayoutState);
245
}
246
247
return NS_OK;
248
}
249
250
NS_IMETHODIMP
251
nsSHEntry::InitLayoutHistoryState(nsILayoutHistoryState** aState) {
252
if (!mShared->mLayoutHistoryState) {
253
nsCOMPtr<nsILayoutHistoryState> historyState;
254
historyState = NS_NewLayoutHistoryState();
255
SetLayoutHistoryState(historyState);
256
}
257
258
nsCOMPtr<nsILayoutHistoryState> state = GetLayoutHistoryState();
259
state.forget(aState);
260
return NS_OK;
261
}
262
263
NS_IMETHODIMP
264
nsSHEntry::GetLoadType(uint32_t* aResult) {
265
*aResult = mLoadType;
266
return NS_OK;
267
}
268
269
NS_IMETHODIMP
270
nsSHEntry::SetLoadType(uint32_t aLoadType) {
271
mLoadType = aLoadType;
272
return NS_OK;
273
}
274
275
NS_IMETHODIMP
276
nsSHEntry::GetID(uint32_t* aResult) {
277
*aResult = mID;
278
return NS_OK;
279
}
280
281
NS_IMETHODIMP
282
nsSHEntry::SetID(uint32_t aID) {
283
mID = aID;
284
return NS_OK;
285
}
286
287
nsSHEntryShared* nsSHEntry::GetSharedState() { return mShared; }
288
289
NS_IMETHODIMP
290
nsSHEntry::GetIsSubFrame(bool* aFlag) {
291
*aFlag = mShared->mIsFrameNavigation;
292
return NS_OK;
293
}
294
295
NS_IMETHODIMP
296
nsSHEntry::SetIsSubFrame(bool aFlag) {
297
mShared->mIsFrameNavigation = aFlag;
298
return NS_OK;
299
}
300
301
NS_IMETHODIMP
302
nsSHEntry::GetCacheKey(uint32_t* aResult) {
303
*aResult = mShared->mCacheKey;
304
return NS_OK;
305
}
306
307
NS_IMETHODIMP
308
nsSHEntry::SetCacheKey(uint32_t aCacheKey) {
309
mShared->mCacheKey = aCacheKey;
310
return NS_OK;
311
}
312
313
NS_IMETHODIMP
314
nsSHEntry::GetSaveLayoutStateFlag(bool* aFlag) {
315
*aFlag = mShared->mSaveLayoutState;
316
return NS_OK;
317
}
318
319
NS_IMETHODIMP
320
nsSHEntry::SetSaveLayoutStateFlag(bool aFlag) {
321
mShared->mSaveLayoutState = aFlag;
322
if (mShared->mLayoutHistoryState) {
323
mShared->mLayoutHistoryState->SetScrollPositionOnly(!aFlag);
324
}
325
326
return NS_OK;
327
}
328
329
NS_IMETHODIMP
330
nsSHEntry::GetExpirationStatus(bool* aFlag) {
331
*aFlag = mShared->mExpired;
332
return NS_OK;
333
}
334
335
NS_IMETHODIMP
336
nsSHEntry::SetExpirationStatus(bool aFlag) {
337
mShared->mExpired = aFlag;
338
return NS_OK;
339
}
340
341
NS_IMETHODIMP
342
nsSHEntry::GetContentType(nsACString& aContentType) {
343
aContentType = mShared->mContentType;
344
return NS_OK;
345
}
346
347
NS_IMETHODIMP
348
nsSHEntry::SetContentType(const nsACString& aContentType) {
349
mShared->mContentType = aContentType;
350
return NS_OK;
351
}
352
353
NS_IMETHODIMP
354
nsSHEntry::Create(nsIURI* aURI, const nsAString& aTitle,
355
nsIInputStream* aInputStream,
356
nsILayoutHistoryState* aLayoutHistoryState,
357
uint32_t aCacheKey, const nsACString& aContentType,
358
nsIPrincipal* aTriggeringPrincipal,
359
nsIPrincipal* aPrincipalToInherit,
360
nsIPrincipal* aStoragePrincipalToInherit,
361
nsIContentSecurityPolicy* aCsp, const nsID& aDocShellID,
362
bool aDynamicCreation) {
363
MOZ_ASSERT(
364
aTriggeringPrincipal,
365
"need a valid triggeringPrincipal to create a session history entry");
366
367
mURI = aURI;
368
mTitle = aTitle;
369
mPostData = aInputStream;
370
371
// Set the LoadType by default to loadHistory during creation
372
mLoadType = LOAD_HISTORY;
373
374
mShared->mCacheKey = aCacheKey;
375
mShared->mContentType = aContentType;
376
mShared->mTriggeringPrincipal = aTriggeringPrincipal;
377
mShared->mPrincipalToInherit = aPrincipalToInherit;
378
mShared->mStoragePrincipalToInherit = aStoragePrincipalToInherit;
379
mShared->mCsp = aCsp;
380
mShared->mDocShellID = aDocShellID;
381
mShared->mDynamicallyCreated = aDynamicCreation;
382
383
// By default all entries are set false for subframe flag.
384
// nsDocShell::CloneAndReplace() which creates entries for
385
// all subframe navigations, sets the flag to true.
386
mShared->mIsFrameNavigation = false;
387
388
// By default we save LayoutHistoryState
389
mShared->mSaveLayoutState = true;
390
mShared->mLayoutHistoryState = aLayoutHistoryState;
391
392
// By default the page is not expired
393
mShared->mExpired = false;
394
395
mIsSrcdocEntry = false;
396
mSrcdocData = VoidString();
397
398
mLoadedInThisProcess = true;
399
400
return NS_OK;
401
}
402
403
NS_IMETHODIMP
404
nsSHEntry::Clone(nsISHEntry** aResult) {
405
*aResult = new nsSHEntry(*this);
406
NS_ADDREF(*aResult);
407
return NS_OK;
408
}
409
410
NS_IMETHODIMP
411
nsSHEntry::GetParent(nsISHEntry** aResult) {
412
*aResult = mParent;
413
NS_IF_ADDREF(*aResult);
414
return NS_OK;
415
}
416
417
NS_IMETHODIMP
418
nsSHEntry::SetParent(nsISHEntry* aParent) {
419
/* parent not Addrefed on purpose to avoid cyclic reference
420
* Null parent is OK
421
*
422
* XXX this method should not be scriptable if this is the case!!
423
*/
424
mParent = aParent;
425
return NS_OK;
426
}
427
428
NS_IMETHODIMP
429
nsSHEntry::SetWindowState(nsISupports* aState) {
430
mShared->mWindowState = aState;
431
return NS_OK;
432
}
433
434
NS_IMETHODIMP
435
nsSHEntry::GetWindowState(nsISupports** aState) {
436
NS_IF_ADDREF(*aState = mShared->mWindowState);
437
return NS_OK;
438
}
439
440
NS_IMETHODIMP_(void)
441
nsSHEntry::SetViewerBounds(const nsIntRect& aBounds) {
442
mShared->mViewerBounds = aBounds;
443
}
444
445
NS_IMETHODIMP_(void)
446
nsSHEntry::GetViewerBounds(nsIntRect& aBounds) {
447
aBounds = mShared->mViewerBounds;
448
}
449
450
NS_IMETHODIMP
451
nsSHEntry::GetTriggeringPrincipal(nsIPrincipal** aTriggeringPrincipal) {
452
NS_IF_ADDREF(*aTriggeringPrincipal = mShared->mTriggeringPrincipal);
453
return NS_OK;
454
}
455
456
NS_IMETHODIMP
457
nsSHEntry::SetTriggeringPrincipal(nsIPrincipal* aTriggeringPrincipal) {
458
mShared->mTriggeringPrincipal = aTriggeringPrincipal;
459
return NS_OK;
460
}
461
462
NS_IMETHODIMP
463
nsSHEntry::GetPrincipalToInherit(nsIPrincipal** aPrincipalToInherit) {
464
NS_IF_ADDREF(*aPrincipalToInherit = mShared->mPrincipalToInherit);
465
return NS_OK;
466
}
467
468
NS_IMETHODIMP
469
nsSHEntry::SetPrincipalToInherit(nsIPrincipal* aPrincipalToInherit) {
470
mShared->mPrincipalToInherit = aPrincipalToInherit;
471
return NS_OK;
472
}
473
474
NS_IMETHODIMP
475
nsSHEntry::GetStoragePrincipalToInherit(
476
nsIPrincipal** aStoragePrincipalToInherit) {
477
NS_IF_ADDREF(*aStoragePrincipalToInherit =
478
mShared->mStoragePrincipalToInherit);
479
return NS_OK;
480
}
481
482
NS_IMETHODIMP
483
nsSHEntry::SetStoragePrincipalToInherit(
484
nsIPrincipal* aStoragePrincipalToInherit) {
485
mShared->mStoragePrincipalToInherit = aStoragePrincipalToInherit;
486
return NS_OK;
487
}
488
489
NS_IMETHODIMP
490
nsSHEntry::GetCsp(nsIContentSecurityPolicy** aCsp) {
491
NS_IF_ADDREF(*aCsp = mShared->mCsp);
492
return NS_OK;
493
}
494
495
NS_IMETHODIMP
496
nsSHEntry::SetCsp(nsIContentSecurityPolicy* aCsp) {
497
mShared->mCsp = aCsp;
498
return NS_OK;
499
}
500
501
NS_IMETHODIMP
502
nsSHEntry::GetBFCacheEntry(nsIBFCacheEntry** aEntry) {
503
NS_IF_ADDREF(*aEntry = mShared);
504
return NS_OK;
505
}
506
507
bool nsSHEntry::HasBFCacheEntry(nsIBFCacheEntry* aEntry) {
508
return static_cast<nsIBFCacheEntry*>(mShared) == aEntry;
509
}
510
511
NS_IMETHODIMP
512
nsSHEntry::AdoptBFCacheEntry(nsISHEntry* aEntry) {
513
nsSHEntryShared* shared = aEntry->GetSharedState();
514
NS_ENSURE_STATE(shared);
515
516
mShared = shared;
517
return NS_OK;
518
}
519
520
NS_IMETHODIMP
521
nsSHEntry::SharesDocumentWith(nsISHEntry* aEntry, bool* aOut) {
522
NS_ENSURE_ARG_POINTER(aOut);
523
524
*aOut = mShared == aEntry->GetSharedState();
525
return NS_OK;
526
}
527
528
NS_IMETHODIMP
529
nsSHEntry::AbandonBFCacheEntry() {
530
mShared = nsSHEntryShared::Duplicate(mShared);
531
return NS_OK;
532
}
533
534
NS_IMETHODIMP
535
nsSHEntry::GetIsSrcdocEntry(bool* aIsSrcdocEntry) {
536
*aIsSrcdocEntry = mIsSrcdocEntry;
537
return NS_OK;
538
}
539
540
NS_IMETHODIMP
541
nsSHEntry::GetSrcdocData(nsAString& aSrcdocData) {
542
aSrcdocData = mSrcdocData;
543
return NS_OK;
544
}
545
546
NS_IMETHODIMP
547
nsSHEntry::SetSrcdocData(const nsAString& aSrcdocData) {
548
mSrcdocData = aSrcdocData;
549
mIsSrcdocEntry = true;
550
return NS_OK;
551
}
552
553
NS_IMETHODIMP
554
nsSHEntry::GetBaseURI(nsIURI** aBaseURI) {
555
*aBaseURI = mBaseURI;
556
NS_IF_ADDREF(*aBaseURI);
557
return NS_OK;
558
}
559
560
NS_IMETHODIMP
561
nsSHEntry::SetBaseURI(nsIURI* aBaseURI) {
562
mBaseURI = aBaseURI;
563
return NS_OK;
564
}
565
566
NS_IMETHODIMP
567
nsSHEntry::GetScrollRestorationIsManual(bool* aIsManual) {
568
*aIsManual = mScrollRestorationIsManual;
569
return NS_OK;
570
}
571
572
NS_IMETHODIMP
573
nsSHEntry::SetScrollRestorationIsManual(bool aIsManual) {
574
mScrollRestorationIsManual = aIsManual;
575
return NS_OK;
576
}
577
578
NS_IMETHODIMP
579
nsSHEntry::GetLoadedInThisProcess(bool* aLoadedInThisProcess) {
580
*aLoadedInThisProcess = mLoadedInThisProcess;
581
return NS_OK;
582
}
583
584
NS_IMETHODIMP
585
nsSHEntry::GetChildCount(int32_t* aCount) {
586
*aCount = mChildren.Count();
587
return NS_OK;
588
}
589
590
NS_IMETHODIMP
591
nsSHEntry::AddChild(nsISHEntry* aChild, int32_t aOffset) {
592
if (aChild) {
593
NS_ENSURE_SUCCESS(aChild->SetParent(this), NS_ERROR_FAILURE);
594
}
595
596
if (aOffset < 0) {
597
mChildren.AppendObject(aChild);
598
return NS_OK;
599
}
600
601
//
602
// Bug 52670: Ensure children are added in order.
603
//
604
// Later frames in the child list may load faster and get appended
605
// before earlier frames, causing session history to be scrambled.
606
// By growing the list here, they are added to the right position.
607
//
608
// Assert that aOffset will not be so high as to grow us a lot.
609
//
610
NS_ASSERTION(aOffset < (mChildren.Count() + 1023), "Large frames array!\n");
611
612
bool newChildIsDyn = aChild ? aChild->IsDynamicallyAdded() : false;
613
614
// If the new child is dynamically added, try to add it to aOffset, but if
615
// there are non-dynamically added children, the child must be after those.
616
if (newChildIsDyn) {
617
int32_t lastNonDyn = aOffset - 1;
618
for (int32_t i = aOffset; i < mChildren.Count(); ++i) {
619
nsISHEntry* entry = mChildren[i];
620
if (entry) {
621
if (entry->IsDynamicallyAdded()) {
622
break;
623
} else {
624
lastNonDyn = i;
625
}
626
}
627
}
628
// InsertObjectAt allows only appending one object.
629
// If aOffset is larger than Count(), we must first manually
630
// set the capacity.
631
if (aOffset > mChildren.Count()) {
632
mChildren.SetCount(aOffset);
633
}
634
if (!mChildren.InsertObjectAt(aChild, lastNonDyn + 1)) {
635
NS_WARNING("Adding a child failed!");
636
aChild->SetParent(nullptr);
637
return NS_ERROR_FAILURE;
638
}
639
} else {
640
// If the new child isn't dynamically added, it should be set to aOffset.
641
// If there are dynamically added children before that, those must be
642
// moved to be after aOffset.
643
if (mChildren.Count() > 0) {
644
int32_t start = std::min(mChildren.Count() - 1, aOffset);
645
int32_t dynEntryIndex = -1;
646
nsISHEntry* dynEntry = nullptr;
647
for (int32_t i = start; i >= 0; --i) {
648
nsISHEntry* entry = mChildren[i];
649
if (entry) {
650
if (entry->IsDynamicallyAdded()) {
651
dynEntryIndex = i;
652
dynEntry = entry;
653
} else {
654
break;
655
}
656
}
657
}
658
659
if (dynEntry) {
660
nsCOMArray<nsISHEntry> tmp;
661
tmp.SetCount(aOffset - dynEntryIndex + 1);
662
mChildren.InsertObjectsAt(tmp, dynEntryIndex);
663
NS_ASSERTION(mChildren[aOffset + 1] == dynEntry, "Whaat?");
664
}
665
}
666
667
// Make sure there isn't anything at aOffset.
668
if (aOffset < mChildren.Count()) {
669
nsISHEntry* oldChild = mChildren[aOffset];
670
if (oldChild && oldChild != aChild) {
671
NS_ERROR(
672
"Adding a child where we already have a child? This may misbehave");
673
oldChild->SetParent(nullptr);
674
}
675
}
676
677
mChildren.ReplaceObjectAt(aChild, aOffset);
678
}
679
680
return NS_OK;
681
}
682
683
NS_IMETHODIMP
684
nsSHEntry::RemoveChild(nsISHEntry* aChild) {
685
NS_ENSURE_TRUE(aChild, NS_ERROR_FAILURE);
686
bool childRemoved = false;
687
if (aChild->IsDynamicallyAdded()) {
688
childRemoved = mChildren.RemoveObject(aChild);
689
} else {
690
int32_t index = mChildren.IndexOfObject(aChild);
691
if (index >= 0) {
692
// Other alive non-dynamic child docshells still keep mChildOffset,
693
// so we don't want to change the indices here.
694
mChildren.ReplaceObjectAt(nullptr, index);
695
childRemoved = true;
696
}
697
}
698
if (childRemoved) {
699
aChild->SetParent(nullptr);
700
701
// reduce the child count, i.e. remove empty children at the end
702
for (int32_t i = mChildren.Count() - 1; i >= 0 && !mChildren[i]; --i) {
703
if (!mChildren.RemoveObjectAt(i)) {
704
break;
705
}
706
}
707
}
708
return NS_OK;
709
}
710
711
NS_IMETHODIMP
712
nsSHEntry::GetChildAt(int32_t aIndex, nsISHEntry** aResult) {
713
if (aIndex >= 0 && aIndex < mChildren.Count()) {
714
*aResult = mChildren[aIndex];
715
// yes, mChildren can have holes in it. AddChild's offset parameter makes
716
// that possible.
717
NS_IF_ADDREF(*aResult);
718
} else {
719
*aResult = nullptr;
720
}
721
return NS_OK;
722
}
723
724
NS_IMETHODIMP
725
nsSHEntry::ReplaceChild(nsISHEntry* aNewEntry) {
726
NS_ENSURE_STATE(aNewEntry);
727
728
nsID docshellID = aNewEntry->DocshellID();
729
730
for (int32_t i = 0; i < mChildren.Count(); ++i) {
731
if (mChildren[i] && docshellID == mChildren[i]->DocshellID()) {
732
mChildren[i]->SetParent(nullptr);
733
mChildren.ReplaceObjectAt(aNewEntry, i);
734
return aNewEntry->SetParent(this);
735
}
736
}
737
return NS_ERROR_FAILURE;
738
}
739
740
NS_IMETHODIMP_(void)
741
nsSHEntry::AddChildShell(nsIDocShellTreeItem* aShell) {
742
MOZ_ASSERT(aShell, "Null child shell added to history entry");
743
mShared->mChildShells.AppendObject(aShell);
744
}
745
746
NS_IMETHODIMP
747
nsSHEntry::ChildShellAt(int32_t aIndex, nsIDocShellTreeItem** aShell) {
748
NS_IF_ADDREF(*aShell = mShared->mChildShells.SafeObjectAt(aIndex));
749
return NS_OK;
750
}
751
752
NS_IMETHODIMP_(void)
753
nsSHEntry::ClearChildShells() { mShared->mChildShells.Clear(); }
754
755
NS_IMETHODIMP
756
nsSHEntry::GetRefreshURIList(nsIMutableArray** aList) {
757
NS_IF_ADDREF(*aList = mShared->mRefreshURIList);
758
return NS_OK;
759
}
760
761
NS_IMETHODIMP
762
nsSHEntry::SetRefreshURIList(nsIMutableArray* aList) {
763
mShared->mRefreshURIList = aList;
764
return NS_OK;
765
}
766
767
NS_IMETHODIMP_(void)
768
nsSHEntry::SyncPresentationState() { mShared->SyncPresentationState(); }
769
770
nsDocShellEditorData* nsSHEntry::ForgetEditorData() {
771
// XXX jlebar Check how this is used.
772
return mShared->mEditorData.forget();
773
}
774
775
void nsSHEntry::SetEditorData(nsDocShellEditorData* aData) {
776
NS_ASSERTION(!(aData && mShared->mEditorData),
777
"We're going to overwrite an owning ref!");
778
if (mShared->mEditorData != aData) {
779
mShared->mEditorData = aData;
780
}
781
}
782
783
bool nsSHEntry::HasDetachedEditor() { return mShared->mEditorData != nullptr; }
784
785
NS_IMETHODIMP
786
nsSHEntry::GetStateData(nsIStructuredCloneContainer** aContainer) {
787
NS_IF_ADDREF(*aContainer = mStateData);
788
return NS_OK;
789
}
790
791
NS_IMETHODIMP
792
nsSHEntry::SetStateData(nsIStructuredCloneContainer* aContainer) {
793
mStateData = aContainer;
794
return NS_OK;
795
}
796
797
NS_IMETHODIMP_(bool)
798
nsSHEntry::IsDynamicallyAdded() { return mShared->mDynamicallyCreated; }
799
800
NS_IMETHODIMP
801
nsSHEntry::HasDynamicallyAddedChild(bool* aAdded) {
802
*aAdded = false;
803
for (int32_t i = 0; i < mChildren.Count(); ++i) {
804
nsISHEntry* entry = mChildren[i];
805
if (entry) {
806
*aAdded = entry->IsDynamicallyAdded();
807
if (*aAdded) {
808
break;
809
}
810
}
811
}
812
return NS_OK;
813
}
814
815
NS_IMETHODIMP
816
nsSHEntry::GetDocshellID(nsID** aID) {
817
*aID = mShared->mDocShellID.Clone();
818
return NS_OK;
819
}
820
821
const nsID nsSHEntry::DocshellID() { return mShared->mDocShellID; }
822
823
NS_IMETHODIMP
824
nsSHEntry::SetDocshellID(const nsID* aID) {
825
mShared->mDocShellID = *aID;
826
return NS_OK;
827
}
828
829
NS_IMETHODIMP
830
nsSHEntry::GetLastTouched(uint32_t* aLastTouched) {
831
*aLastTouched = mShared->mLastTouched;
832
return NS_OK;
833
}
834
835
NS_IMETHODIMP
836
nsSHEntry::SetLastTouched(uint32_t aLastTouched) {
837
mShared->mLastTouched = aLastTouched;
838
return NS_OK;
839
}
840
841
NS_IMETHODIMP
842
nsSHEntry::GetSHistory(nsISHistory** aSHistory) {
843
nsCOMPtr<nsISHistory> shistory(do_QueryReferent(mShared->mSHistory));
844
shistory.forget(aSHistory);
845
return NS_OK;
846
}
847
848
NS_IMETHODIMP
849
nsSHEntry::SetSHistory(nsISHistory* aSHistory) {
850
nsWeakPtr shistory = do_GetWeakReference(aSHistory);
851
// mSHistory can not be changed once it's set
852
MOZ_ASSERT(!mShared->mSHistory || (mShared->mSHistory == shistory));
853
mShared->mSHistory = shistory;
854
return NS_OK;
855
}
856
857
NS_IMETHODIMP
858
nsSHEntry::SetLoadTypeAsHistory() {
859
// Set the LoadType by default to loadHistory during creation
860
mLoadType = LOAD_HISTORY;
861
return NS_OK;
862
}
863
864
NS_IMETHODIMP
865
nsSHEntry::GetPersist(bool* aPersist) {
866
*aPersist = mPersist;
867
return NS_OK;
868
}
869
870
NS_IMETHODIMP
871
nsSHEntry::SetPersist(bool aPersist) {
872
mPersist = aPersist;
873
return NS_OK;
874
}