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