nsSHEntry.cpp 20 KB

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