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