1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/docshell/shistory/src/nsSHEntry.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,835 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +// Local Includes 1.10 +#include "nsSHEntry.h" 1.11 +#include "nsIDocShellLoadInfo.h" 1.12 +#include "nsIDocShellTreeItem.h" 1.13 +#include "nsDocShellEditorData.h" 1.14 +#include "nsSHEntryShared.h" 1.15 +#include "nsILayoutHistoryState.h" 1.16 +#include "nsIContentViewer.h" 1.17 +#include "nsISupportsArray.h" 1.18 +#include "nsIStructuredCloneContainer.h" 1.19 +#include "nsIInputStream.h" 1.20 +#include "nsIURI.h" 1.21 +#include <algorithm> 1.22 + 1.23 +namespace dom = mozilla::dom; 1.24 + 1.25 +static uint32_t gEntryID = 0; 1.26 + 1.27 +//***************************************************************************** 1.28 +//*** nsSHEntry: Object Management 1.29 +//***************************************************************************** 1.30 + 1.31 + 1.32 +nsSHEntry::nsSHEntry() 1.33 + : mLoadType(0) 1.34 + , mID(gEntryID++) 1.35 + , mScrollPositionX(0) 1.36 + , mScrollPositionY(0) 1.37 + , mParent(nullptr) 1.38 + , mURIWasModified(false) 1.39 + , mIsSrcdocEntry(false) 1.40 +{ 1.41 + mShared = new nsSHEntryShared(); 1.42 +} 1.43 + 1.44 +nsSHEntry::nsSHEntry(const nsSHEntry &other) 1.45 + : mShared(other.mShared) 1.46 + , mURI(other.mURI) 1.47 + , mReferrerURI(other.mReferrerURI) 1.48 + , mTitle(other.mTitle) 1.49 + , mPostData(other.mPostData) 1.50 + , mLoadType(0) // XXX why not copy? 1.51 + , mID(other.mID) 1.52 + , mScrollPositionX(0) // XXX why not copy? 1.53 + , mScrollPositionY(0) // XXX why not copy? 1.54 + , mParent(other.mParent) 1.55 + , mURIWasModified(other.mURIWasModified) 1.56 + , mStateData(other.mStateData) 1.57 + , mIsSrcdocEntry(other.mIsSrcdocEntry) 1.58 + , mSrcdocData(other.mSrcdocData) 1.59 + , mBaseURI(other.mBaseURI) 1.60 +{ 1.61 +} 1.62 + 1.63 +static bool 1.64 +ClearParentPtr(nsISHEntry* aEntry, void* /* aData */) 1.65 +{ 1.66 + if (aEntry) { 1.67 + aEntry->SetParent(nullptr); 1.68 + } 1.69 + return true; 1.70 +} 1.71 + 1.72 +nsSHEntry::~nsSHEntry() 1.73 +{ 1.74 + // Null out the mParent pointers on all our kids. 1.75 + mChildren.EnumerateForwards(ClearParentPtr, nullptr); 1.76 +} 1.77 + 1.78 +//***************************************************************************** 1.79 +// nsSHEntry: nsISupports 1.80 +//***************************************************************************** 1.81 + 1.82 +NS_IMPL_ISUPPORTS(nsSHEntry, nsISHContainer, nsISHEntry, nsISHEntryInternal) 1.83 + 1.84 +//***************************************************************************** 1.85 +// nsSHEntry: nsISHEntry 1.86 +//***************************************************************************** 1.87 + 1.88 +NS_IMETHODIMP nsSHEntry::SetScrollPosition(int32_t x, int32_t y) 1.89 +{ 1.90 + mScrollPositionX = x; 1.91 + mScrollPositionY = y; 1.92 + return NS_OK; 1.93 +} 1.94 + 1.95 +NS_IMETHODIMP nsSHEntry::GetScrollPosition(int32_t *x, int32_t *y) 1.96 +{ 1.97 + *x = mScrollPositionX; 1.98 + *y = mScrollPositionY; 1.99 + return NS_OK; 1.100 +} 1.101 + 1.102 +NS_IMETHODIMP nsSHEntry::GetURIWasModified(bool* aOut) 1.103 +{ 1.104 + *aOut = mURIWasModified; 1.105 + return NS_OK; 1.106 +} 1.107 + 1.108 +NS_IMETHODIMP nsSHEntry::SetURIWasModified(bool aIn) 1.109 +{ 1.110 + mURIWasModified = aIn; 1.111 + return NS_OK; 1.112 +} 1.113 + 1.114 +NS_IMETHODIMP nsSHEntry::GetURI(nsIURI** aURI) 1.115 +{ 1.116 + *aURI = mURI; 1.117 + NS_IF_ADDREF(*aURI); 1.118 + return NS_OK; 1.119 +} 1.120 + 1.121 +NS_IMETHODIMP nsSHEntry::SetURI(nsIURI* aURI) 1.122 +{ 1.123 + mURI = aURI; 1.124 + return NS_OK; 1.125 +} 1.126 + 1.127 +NS_IMETHODIMP nsSHEntry::GetReferrerURI(nsIURI **aReferrerURI) 1.128 +{ 1.129 + *aReferrerURI = mReferrerURI; 1.130 + NS_IF_ADDREF(*aReferrerURI); 1.131 + return NS_OK; 1.132 +} 1.133 + 1.134 +NS_IMETHODIMP nsSHEntry::SetReferrerURI(nsIURI *aReferrerURI) 1.135 +{ 1.136 + mReferrerURI = aReferrerURI; 1.137 + return NS_OK; 1.138 +} 1.139 + 1.140 +NS_IMETHODIMP 1.141 +nsSHEntry::SetContentViewer(nsIContentViewer *aViewer) 1.142 +{ 1.143 + return mShared->SetContentViewer(aViewer); 1.144 +} 1.145 + 1.146 +NS_IMETHODIMP 1.147 +nsSHEntry::GetContentViewer(nsIContentViewer **aResult) 1.148 +{ 1.149 + *aResult = mShared->mContentViewer; 1.150 + NS_IF_ADDREF(*aResult); 1.151 + return NS_OK; 1.152 +} 1.153 + 1.154 +NS_IMETHODIMP 1.155 +nsSHEntry::GetAnyContentViewer(nsISHEntry **aOwnerEntry, 1.156 + nsIContentViewer **aResult) 1.157 +{ 1.158 + // Find a content viewer in the root node or any of its children, 1.159 + // assuming that there is only one content viewer total in any one 1.160 + // nsSHEntry tree 1.161 + GetContentViewer(aResult); 1.162 + if (*aResult) { 1.163 +#ifdef DEBUG_PAGE_CACHE 1.164 + printf("Found content viewer\n"); 1.165 +#endif 1.166 + *aOwnerEntry = this; 1.167 + NS_ADDREF(*aOwnerEntry); 1.168 + return NS_OK; 1.169 + } 1.170 + // The root SHEntry doesn't have a ContentViewer, so check child nodes 1.171 + for (int32_t i = 0; i < mChildren.Count(); i++) { 1.172 + nsISHEntry* child = mChildren[i]; 1.173 + if (child) { 1.174 +#ifdef DEBUG_PAGE_CACHE 1.175 + printf("Evaluating SHEntry child %d\n", i); 1.176 +#endif 1.177 + child->GetAnyContentViewer(aOwnerEntry, aResult); 1.178 + if (*aResult) { 1.179 + return NS_OK; 1.180 + } 1.181 + } 1.182 + } 1.183 + return NS_OK; 1.184 +} 1.185 + 1.186 +NS_IMETHODIMP 1.187 +nsSHEntry::SetSticky(bool aSticky) 1.188 +{ 1.189 + mShared->mSticky = aSticky; 1.190 + return NS_OK; 1.191 +} 1.192 + 1.193 +NS_IMETHODIMP 1.194 +nsSHEntry::GetSticky(bool *aSticky) 1.195 +{ 1.196 + *aSticky = mShared->mSticky; 1.197 + return NS_OK; 1.198 +} 1.199 + 1.200 +NS_IMETHODIMP nsSHEntry::GetTitle(char16_t** aTitle) 1.201 +{ 1.202 + // Check for empty title... 1.203 + if (mTitle.IsEmpty() && mURI) { 1.204 + // Default title is the URL. 1.205 + nsAutoCString spec; 1.206 + if (NS_SUCCEEDED(mURI->GetSpec(spec))) 1.207 + AppendUTF8toUTF16(spec, mTitle); 1.208 + } 1.209 + 1.210 + *aTitle = ToNewUnicode(mTitle); 1.211 + return NS_OK; 1.212 +} 1.213 + 1.214 +NS_IMETHODIMP nsSHEntry::SetTitle(const nsAString &aTitle) 1.215 +{ 1.216 + mTitle = aTitle; 1.217 + return NS_OK; 1.218 +} 1.219 + 1.220 +NS_IMETHODIMP nsSHEntry::GetPostData(nsIInputStream** aResult) 1.221 +{ 1.222 + *aResult = mPostData; 1.223 + NS_IF_ADDREF(*aResult); 1.224 + return NS_OK; 1.225 +} 1.226 + 1.227 +NS_IMETHODIMP nsSHEntry::SetPostData(nsIInputStream* aPostData) 1.228 +{ 1.229 + mPostData = aPostData; 1.230 + return NS_OK; 1.231 +} 1.232 + 1.233 +NS_IMETHODIMP nsSHEntry::GetLayoutHistoryState(nsILayoutHistoryState** aResult) 1.234 +{ 1.235 + *aResult = mShared->mLayoutHistoryState; 1.236 + NS_IF_ADDREF(*aResult); 1.237 + return NS_OK; 1.238 +} 1.239 + 1.240 +NS_IMETHODIMP nsSHEntry::SetLayoutHistoryState(nsILayoutHistoryState* aState) 1.241 +{ 1.242 + mShared->mLayoutHistoryState = aState; 1.243 + if (mShared->mLayoutHistoryState) { 1.244 + mShared->mLayoutHistoryState-> 1.245 + SetScrollPositionOnly(!mShared->mSaveLayoutState); 1.246 + } 1.247 + 1.248 + return NS_OK; 1.249 +} 1.250 + 1.251 +NS_IMETHODIMP nsSHEntry::GetLoadType(uint32_t * aResult) 1.252 +{ 1.253 + *aResult = mLoadType; 1.254 + return NS_OK; 1.255 +} 1.256 + 1.257 +NS_IMETHODIMP nsSHEntry::SetLoadType(uint32_t aLoadType) 1.258 +{ 1.259 + mLoadType = aLoadType; 1.260 + return NS_OK; 1.261 +} 1.262 + 1.263 +NS_IMETHODIMP nsSHEntry::GetID(uint32_t * aResult) 1.264 +{ 1.265 + *aResult = mID; 1.266 + return NS_OK; 1.267 +} 1.268 + 1.269 +NS_IMETHODIMP nsSHEntry::SetID(uint32_t aID) 1.270 +{ 1.271 + mID = aID; 1.272 + return NS_OK; 1.273 +} 1.274 + 1.275 +nsSHEntryShared* nsSHEntry::GetSharedState() 1.276 +{ 1.277 + return mShared; 1.278 +} 1.279 + 1.280 +NS_IMETHODIMP nsSHEntry::GetIsSubFrame(bool * aFlag) 1.281 +{ 1.282 + *aFlag = mShared->mIsFrameNavigation; 1.283 + return NS_OK; 1.284 +} 1.285 + 1.286 +NS_IMETHODIMP nsSHEntry::SetIsSubFrame(bool aFlag) 1.287 +{ 1.288 + mShared->mIsFrameNavigation = aFlag; 1.289 + return NS_OK; 1.290 +} 1.291 + 1.292 +NS_IMETHODIMP nsSHEntry::GetCacheKey(nsISupports** aResult) 1.293 +{ 1.294 + *aResult = mShared->mCacheKey; 1.295 + NS_IF_ADDREF(*aResult); 1.296 + return NS_OK; 1.297 +} 1.298 + 1.299 +NS_IMETHODIMP nsSHEntry::SetCacheKey(nsISupports* aCacheKey) 1.300 +{ 1.301 + mShared->mCacheKey = aCacheKey; 1.302 + return NS_OK; 1.303 +} 1.304 + 1.305 +NS_IMETHODIMP nsSHEntry::GetSaveLayoutStateFlag(bool * aFlag) 1.306 +{ 1.307 + *aFlag = mShared->mSaveLayoutState; 1.308 + return NS_OK; 1.309 +} 1.310 + 1.311 +NS_IMETHODIMP nsSHEntry::SetSaveLayoutStateFlag(bool aFlag) 1.312 +{ 1.313 + mShared->mSaveLayoutState = aFlag; 1.314 + if (mShared->mLayoutHistoryState) { 1.315 + mShared->mLayoutHistoryState->SetScrollPositionOnly(!aFlag); 1.316 + } 1.317 + 1.318 + return NS_OK; 1.319 +} 1.320 + 1.321 +NS_IMETHODIMP nsSHEntry::GetExpirationStatus(bool * aFlag) 1.322 +{ 1.323 + *aFlag = mShared->mExpired; 1.324 + return NS_OK; 1.325 +} 1.326 + 1.327 +NS_IMETHODIMP nsSHEntry::SetExpirationStatus(bool aFlag) 1.328 +{ 1.329 + mShared->mExpired = aFlag; 1.330 + return NS_OK; 1.331 +} 1.332 + 1.333 +NS_IMETHODIMP nsSHEntry::GetContentType(nsACString& aContentType) 1.334 +{ 1.335 + aContentType = mShared->mContentType; 1.336 + return NS_OK; 1.337 +} 1.338 + 1.339 +NS_IMETHODIMP nsSHEntry::SetContentType(const nsACString& aContentType) 1.340 +{ 1.341 + mShared->mContentType = aContentType; 1.342 + return NS_OK; 1.343 +} 1.344 + 1.345 +NS_IMETHODIMP 1.346 +nsSHEntry::Create(nsIURI * aURI, const nsAString &aTitle, 1.347 + nsIInputStream * aInputStream, 1.348 + nsILayoutHistoryState * aLayoutHistoryState, 1.349 + nsISupports * aCacheKey, const nsACString& aContentType, 1.350 + nsISupports* aOwner, 1.351 + uint64_t aDocShellID, bool aDynamicCreation) 1.352 +{ 1.353 + mURI = aURI; 1.354 + mTitle = aTitle; 1.355 + mPostData = aInputStream; 1.356 + 1.357 + // Set the LoadType by default to loadHistory during creation 1.358 + mLoadType = (uint32_t) nsIDocShellLoadInfo::loadHistory; 1.359 + 1.360 + mShared->mCacheKey = aCacheKey; 1.361 + mShared->mContentType = aContentType; 1.362 + mShared->mOwner = aOwner; 1.363 + mShared->mDocShellID = aDocShellID; 1.364 + mShared->mDynamicallyCreated = aDynamicCreation; 1.365 + 1.366 + // By default all entries are set false for subframe flag. 1.367 + // nsDocShell::CloneAndReplace() which creates entries for 1.368 + // all subframe navigations, sets the flag to true. 1.369 + mShared->mIsFrameNavigation = false; 1.370 + 1.371 + // By default we save LayoutHistoryState 1.372 + mShared->mSaveLayoutState = true; 1.373 + mShared->mLayoutHistoryState = aLayoutHistoryState; 1.374 + 1.375 + //By default the page is not expired 1.376 + mShared->mExpired = false; 1.377 + 1.378 + mIsSrcdocEntry = false; 1.379 + mSrcdocData = NullString(); 1.380 + 1.381 + return NS_OK; 1.382 +} 1.383 + 1.384 +NS_IMETHODIMP 1.385 +nsSHEntry::Clone(nsISHEntry ** aResult) 1.386 +{ 1.387 + *aResult = new nsSHEntry(*this); 1.388 + NS_ADDREF(*aResult); 1.389 + return NS_OK; 1.390 +} 1.391 + 1.392 +NS_IMETHODIMP 1.393 +nsSHEntry::GetParent(nsISHEntry ** aResult) 1.394 +{ 1.395 + NS_ENSURE_ARG_POINTER(aResult); 1.396 + *aResult = mParent; 1.397 + NS_IF_ADDREF(*aResult); 1.398 + return NS_OK; 1.399 +} 1.400 + 1.401 +NS_IMETHODIMP 1.402 +nsSHEntry::SetParent(nsISHEntry * aParent) 1.403 +{ 1.404 + /* parent not Addrefed on purpose to avoid cyclic reference 1.405 + * Null parent is OK 1.406 + * 1.407 + * XXX this method should not be scriptable if this is the case!! 1.408 + */ 1.409 + mParent = aParent; 1.410 + return NS_OK; 1.411 +} 1.412 + 1.413 +NS_IMETHODIMP 1.414 +nsSHEntry::SetWindowState(nsISupports *aState) 1.415 +{ 1.416 + mShared->mWindowState = aState; 1.417 + return NS_OK; 1.418 +} 1.419 + 1.420 +NS_IMETHODIMP 1.421 +nsSHEntry::GetWindowState(nsISupports **aState) 1.422 +{ 1.423 + NS_IF_ADDREF(*aState = mShared->mWindowState); 1.424 + return NS_OK; 1.425 +} 1.426 + 1.427 +NS_IMETHODIMP 1.428 +nsSHEntry::SetViewerBounds(const nsIntRect &aBounds) 1.429 +{ 1.430 + mShared->mViewerBounds = aBounds; 1.431 + return NS_OK; 1.432 +} 1.433 + 1.434 +NS_IMETHODIMP 1.435 +nsSHEntry::GetViewerBounds(nsIntRect &aBounds) 1.436 +{ 1.437 + aBounds = mShared->mViewerBounds; 1.438 + return NS_OK; 1.439 +} 1.440 + 1.441 +NS_IMETHODIMP 1.442 +nsSHEntry::GetOwner(nsISupports **aOwner) 1.443 +{ 1.444 + NS_IF_ADDREF(*aOwner = mShared->mOwner); 1.445 + return NS_OK; 1.446 +} 1.447 + 1.448 +NS_IMETHODIMP 1.449 +nsSHEntry::SetOwner(nsISupports *aOwner) 1.450 +{ 1.451 + mShared->mOwner = aOwner; 1.452 + return NS_OK; 1.453 +} 1.454 + 1.455 +NS_IMETHODIMP 1.456 +nsSHEntry::GetBFCacheEntry(nsIBFCacheEntry **aEntry) 1.457 +{ 1.458 + NS_ENSURE_ARG_POINTER(aEntry); 1.459 + NS_IF_ADDREF(*aEntry = mShared); 1.460 + return NS_OK; 1.461 +} 1.462 + 1.463 +bool 1.464 +nsSHEntry::HasBFCacheEntry(nsIBFCacheEntry *aEntry) 1.465 +{ 1.466 + return static_cast<nsIBFCacheEntry*>(mShared) == aEntry; 1.467 +} 1.468 + 1.469 +NS_IMETHODIMP 1.470 +nsSHEntry::AdoptBFCacheEntry(nsISHEntry *aEntry) 1.471 +{ 1.472 + nsCOMPtr<nsISHEntryInternal> shEntry = do_QueryInterface(aEntry); 1.473 + NS_ENSURE_STATE(shEntry); 1.474 + 1.475 + nsSHEntryShared *shared = shEntry->GetSharedState(); 1.476 + NS_ENSURE_STATE(shared); 1.477 + 1.478 + mShared = shared; 1.479 + return NS_OK; 1.480 +} 1.481 + 1.482 +NS_IMETHODIMP 1.483 +nsSHEntry::SharesDocumentWith(nsISHEntry *aEntry, bool *aOut) 1.484 +{ 1.485 + NS_ENSURE_ARG_POINTER(aOut); 1.486 + 1.487 + nsCOMPtr<nsISHEntryInternal> internal = do_QueryInterface(aEntry); 1.488 + NS_ENSURE_STATE(internal); 1.489 + 1.490 + *aOut = mShared == internal->GetSharedState(); 1.491 + return NS_OK; 1.492 +} 1.493 + 1.494 +NS_IMETHODIMP 1.495 +nsSHEntry::AbandonBFCacheEntry() 1.496 +{ 1.497 + mShared = nsSHEntryShared::Duplicate(mShared); 1.498 + return NS_OK; 1.499 +} 1.500 + 1.501 +NS_IMETHODIMP 1.502 +nsSHEntry::GetIsSrcdocEntry(bool* aIsSrcdocEntry) 1.503 +{ 1.504 + *aIsSrcdocEntry = mIsSrcdocEntry; 1.505 + return NS_OK; 1.506 +} 1.507 + 1.508 +NS_IMETHODIMP 1.509 +nsSHEntry::GetSrcdocData(nsAString &aSrcdocData) 1.510 +{ 1.511 + aSrcdocData = mSrcdocData; 1.512 + return NS_OK; 1.513 +} 1.514 + 1.515 +NS_IMETHODIMP 1.516 +nsSHEntry::SetSrcdocData(const nsAString &aSrcdocData) 1.517 +{ 1.518 + mSrcdocData = aSrcdocData; 1.519 + mIsSrcdocEntry = true; 1.520 + return NS_OK; 1.521 +} 1.522 + 1.523 +NS_IMETHODIMP 1.524 +nsSHEntry::GetBaseURI(nsIURI **aBaseURI) 1.525 +{ 1.526 + *aBaseURI = mBaseURI; 1.527 + NS_IF_ADDREF(*aBaseURI); 1.528 + return NS_OK; 1.529 +} 1.530 + 1.531 +NS_IMETHODIMP 1.532 +nsSHEntry::SetBaseURI(nsIURI *aBaseURI) 1.533 +{ 1.534 + mBaseURI = aBaseURI; 1.535 + return NS_OK; 1.536 +} 1.537 + 1.538 +//***************************************************************************** 1.539 +// nsSHEntry: nsISHContainer 1.540 +//***************************************************************************** 1.541 + 1.542 +NS_IMETHODIMP 1.543 +nsSHEntry::GetChildCount(int32_t * aCount) 1.544 +{ 1.545 + *aCount = mChildren.Count(); 1.546 + return NS_OK; 1.547 +} 1.548 + 1.549 +NS_IMETHODIMP 1.550 +nsSHEntry::AddChild(nsISHEntry * aChild, int32_t aOffset) 1.551 +{ 1.552 + if (aChild) { 1.553 + NS_ENSURE_SUCCESS(aChild->SetParent(this), NS_ERROR_FAILURE); 1.554 + } 1.555 + 1.556 + if (aOffset < 0) { 1.557 + mChildren.AppendObject(aChild); 1.558 + return NS_OK; 1.559 + } 1.560 + 1.561 + // 1.562 + // Bug 52670: Ensure children are added in order. 1.563 + // 1.564 + // Later frames in the child list may load faster and get appended 1.565 + // before earlier frames, causing session history to be scrambled. 1.566 + // By growing the list here, they are added to the right position. 1.567 + // 1.568 + // Assert that aOffset will not be so high as to grow us a lot. 1.569 + // 1.570 + NS_ASSERTION(aOffset < (mChildren.Count()+1023), "Large frames array!\n"); 1.571 + 1.572 + bool newChildIsDyn = false; 1.573 + if (aChild) { 1.574 + aChild->IsDynamicallyAdded(&newChildIsDyn); 1.575 + } 1.576 + 1.577 + // If the new child is dynamically added, try to add it to aOffset, but if 1.578 + // there are non-dynamically added children, the child must be after those. 1.579 + if (newChildIsDyn) { 1.580 + int32_t lastNonDyn = aOffset - 1; 1.581 + for (int32_t i = aOffset; i < mChildren.Count(); ++i) { 1.582 + nsISHEntry* entry = mChildren[i]; 1.583 + if (entry) { 1.584 + bool dyn = false; 1.585 + entry->IsDynamicallyAdded(&dyn); 1.586 + if (dyn) { 1.587 + break; 1.588 + } else { 1.589 + lastNonDyn = i; 1.590 + } 1.591 + } 1.592 + } 1.593 + // InsertObjectAt allows only appending one object. 1.594 + // If aOffset is larger than Count(), we must first manually 1.595 + // set the capacity. 1.596 + if (aOffset > mChildren.Count()) { 1.597 + mChildren.SetCount(aOffset); 1.598 + } 1.599 + if (!mChildren.InsertObjectAt(aChild, lastNonDyn + 1)) { 1.600 + NS_WARNING("Adding a child failed!"); 1.601 + aChild->SetParent(nullptr); 1.602 + return NS_ERROR_FAILURE; 1.603 + } 1.604 + } else { 1.605 + // If the new child isn't dynamically added, it should be set to aOffset. 1.606 + // If there are dynamically added children before that, those must be 1.607 + // moved to be after aOffset. 1.608 + if (mChildren.Count() > 0) { 1.609 + int32_t start = std::min(mChildren.Count() - 1, aOffset); 1.610 + int32_t dynEntryIndex = -1; 1.611 + nsISHEntry* dynEntry = nullptr; 1.612 + for (int32_t i = start; i >= 0; --i) { 1.613 + nsISHEntry* entry = mChildren[i]; 1.614 + if (entry) { 1.615 + bool dyn = false; 1.616 + entry->IsDynamicallyAdded(&dyn); 1.617 + if (dyn) { 1.618 + dynEntryIndex = i; 1.619 + dynEntry = entry; 1.620 + } else { 1.621 + break; 1.622 + } 1.623 + } 1.624 + } 1.625 + 1.626 + if (dynEntry) { 1.627 + nsCOMArray<nsISHEntry> tmp; 1.628 + tmp.SetCount(aOffset - dynEntryIndex + 1); 1.629 + mChildren.InsertObjectsAt(tmp, dynEntryIndex); 1.630 + NS_ASSERTION(mChildren[aOffset + 1] == dynEntry, "Whaat?"); 1.631 + } 1.632 + } 1.633 + 1.634 + 1.635 + // Make sure there isn't anything at aOffset. 1.636 + if (aOffset < mChildren.Count()) { 1.637 + nsISHEntry* oldChild = mChildren[aOffset]; 1.638 + if (oldChild && oldChild != aChild) { 1.639 + NS_ERROR("Adding a child where we already have a child? This may misbehave"); 1.640 + oldChild->SetParent(nullptr); 1.641 + } 1.642 + } 1.643 + 1.644 + if (!mChildren.ReplaceObjectAt(aChild, aOffset)) { 1.645 + NS_WARNING("Adding a child failed!"); 1.646 + aChild->SetParent(nullptr); 1.647 + return NS_ERROR_FAILURE; 1.648 + } 1.649 + } 1.650 + 1.651 + return NS_OK; 1.652 +} 1.653 + 1.654 +NS_IMETHODIMP 1.655 +nsSHEntry::RemoveChild(nsISHEntry * aChild) 1.656 +{ 1.657 + NS_ENSURE_TRUE(aChild, NS_ERROR_FAILURE); 1.658 + bool childRemoved = false; 1.659 + bool dynamic = false; 1.660 + aChild->IsDynamicallyAdded(&dynamic); 1.661 + if (dynamic) { 1.662 + childRemoved = mChildren.RemoveObject(aChild); 1.663 + } else { 1.664 + int32_t index = mChildren.IndexOfObject(aChild); 1.665 + if (index >= 0) { 1.666 + childRemoved = mChildren.ReplaceObjectAt(nullptr, index); 1.667 + } 1.668 + } 1.669 + if (childRemoved) { 1.670 + aChild->SetParent(nullptr); 1.671 + 1.672 + // reduce the child count, i.e. remove empty children at the end 1.673 + for (int32_t i = mChildren.Count() - 1; i >= 0 && !mChildren[i]; --i) { 1.674 + if (!mChildren.RemoveObjectAt(i)) { 1.675 + break; 1.676 + } 1.677 + } 1.678 + } 1.679 + return NS_OK; 1.680 +} 1.681 + 1.682 +NS_IMETHODIMP 1.683 +nsSHEntry::GetChildAt(int32_t aIndex, nsISHEntry ** aResult) 1.684 +{ 1.685 + if (aIndex >= 0 && aIndex < mChildren.Count()) { 1.686 + *aResult = mChildren[aIndex]; 1.687 + // yes, mChildren can have holes in it. AddChild's offset parameter makes 1.688 + // that possible. 1.689 + NS_IF_ADDREF(*aResult); 1.690 + } else { 1.691 + *aResult = nullptr; 1.692 + } 1.693 + return NS_OK; 1.694 +} 1.695 + 1.696 +NS_IMETHODIMP 1.697 +nsSHEntry::AddChildShell(nsIDocShellTreeItem *aShell) 1.698 +{ 1.699 + NS_ASSERTION(aShell, "Null child shell added to history entry"); 1.700 + mShared->mChildShells.AppendObject(aShell); 1.701 + return NS_OK; 1.702 +} 1.703 + 1.704 +NS_IMETHODIMP 1.705 +nsSHEntry::ChildShellAt(int32_t aIndex, nsIDocShellTreeItem **aShell) 1.706 +{ 1.707 + NS_IF_ADDREF(*aShell = mShared->mChildShells.SafeObjectAt(aIndex)); 1.708 + return NS_OK; 1.709 +} 1.710 + 1.711 +NS_IMETHODIMP 1.712 +nsSHEntry::ClearChildShells() 1.713 +{ 1.714 + mShared->mChildShells.Clear(); 1.715 + return NS_OK; 1.716 +} 1.717 + 1.718 +NS_IMETHODIMP 1.719 +nsSHEntry::GetRefreshURIList(nsISupportsArray **aList) 1.720 +{ 1.721 + NS_IF_ADDREF(*aList = mShared->mRefreshURIList); 1.722 + return NS_OK; 1.723 +} 1.724 + 1.725 +NS_IMETHODIMP 1.726 +nsSHEntry::SetRefreshURIList(nsISupportsArray *aList) 1.727 +{ 1.728 + mShared->mRefreshURIList = aList; 1.729 + return NS_OK; 1.730 +} 1.731 + 1.732 +NS_IMETHODIMP 1.733 +nsSHEntry::SyncPresentationState() 1.734 +{ 1.735 + return mShared->SyncPresentationState(); 1.736 +} 1.737 + 1.738 +void 1.739 +nsSHEntry::RemoveFromBFCacheSync() 1.740 +{ 1.741 + mShared->RemoveFromBFCacheSync(); 1.742 +} 1.743 + 1.744 +void 1.745 +nsSHEntry::RemoveFromBFCacheAsync() 1.746 +{ 1.747 + mShared->RemoveFromBFCacheAsync(); 1.748 +} 1.749 + 1.750 +nsDocShellEditorData* 1.751 +nsSHEntry::ForgetEditorData() 1.752 +{ 1.753 + // XXX jlebar Check how this is used. 1.754 + return mShared->mEditorData.forget(); 1.755 +} 1.756 + 1.757 +void 1.758 +nsSHEntry::SetEditorData(nsDocShellEditorData* aData) 1.759 +{ 1.760 + NS_ASSERTION(!(aData && mShared->mEditorData), 1.761 + "We're going to overwrite an owning ref!"); 1.762 + if (mShared->mEditorData != aData) { 1.763 + mShared->mEditorData = aData; 1.764 + } 1.765 +} 1.766 + 1.767 +bool 1.768 +nsSHEntry::HasDetachedEditor() 1.769 +{ 1.770 + return mShared->mEditorData != nullptr; 1.771 +} 1.772 + 1.773 +NS_IMETHODIMP 1.774 +nsSHEntry::GetStateData(nsIStructuredCloneContainer **aContainer) 1.775 +{ 1.776 + NS_ENSURE_ARG_POINTER(aContainer); 1.777 + NS_IF_ADDREF(*aContainer = mStateData); 1.778 + return NS_OK; 1.779 +} 1.780 + 1.781 +NS_IMETHODIMP 1.782 +nsSHEntry::SetStateData(nsIStructuredCloneContainer *aContainer) 1.783 +{ 1.784 + mStateData = aContainer; 1.785 + return NS_OK; 1.786 +} 1.787 + 1.788 +NS_IMETHODIMP 1.789 +nsSHEntry::IsDynamicallyAdded(bool* aAdded) 1.790 +{ 1.791 + *aAdded = mShared->mDynamicallyCreated; 1.792 + return NS_OK; 1.793 +} 1.794 + 1.795 +NS_IMETHODIMP 1.796 +nsSHEntry::HasDynamicallyAddedChild(bool* aAdded) 1.797 +{ 1.798 + *aAdded = false; 1.799 + for (int32_t i = 0; i < mChildren.Count(); ++i) { 1.800 + nsISHEntry* entry = mChildren[i]; 1.801 + if (entry) { 1.802 + entry->IsDynamicallyAdded(aAdded); 1.803 + if (*aAdded) { 1.804 + break; 1.805 + } 1.806 + } 1.807 + } 1.808 + return NS_OK; 1.809 +} 1.810 + 1.811 +NS_IMETHODIMP 1.812 +nsSHEntry::GetDocshellID(uint64_t* aID) 1.813 +{ 1.814 + *aID = mShared->mDocShellID; 1.815 + return NS_OK; 1.816 +} 1.817 + 1.818 +NS_IMETHODIMP 1.819 +nsSHEntry::SetDocshellID(uint64_t aID) 1.820 +{ 1.821 + mShared->mDocShellID = aID; 1.822 + return NS_OK; 1.823 +} 1.824 + 1.825 + 1.826 +NS_IMETHODIMP 1.827 +nsSHEntry::GetLastTouched(uint32_t *aLastTouched) 1.828 +{ 1.829 + *aLastTouched = mShared->mLastTouched; 1.830 + return NS_OK; 1.831 +} 1.832 + 1.833 +NS_IMETHODIMP 1.834 +nsSHEntry::SetLastTouched(uint32_t aLastTouched) 1.835 +{ 1.836 + mShared->mLastTouched = aLastTouched; 1.837 + return NS_OK; 1.838 +}