docshell/shistory/src/nsSHEntry.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial