LCOV - code coverage report
Current view: top level - dom/base - GroupedSHistory.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 6 179 3.4 %
Date: 2017-07-14 16:53:18 Functions: 3 21 14.3 %
Legend: Lines: hit not hit

          Line data    Source code
       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 "GroupedSHistory.h"
       8             : 
       9             : #include "mozilla/dom/Promise.h"
      10             : #include "TabParent.h"
      11             : #include "PartialSHistory.h"
      12             : 
      13             : namespace mozilla {
      14             : namespace dom {
      15             : 
      16             : NS_IMPL_CYCLE_COLLECTION_CLASS(GroupedSHistory)
      17             : 
      18           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(GroupedSHistory)
      19           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPartialHistories)
      20           0 :   tmp->mPrerenderingHistories.Clear();
      21           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
      22             : 
      23           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(GroupedSHistory)
      24           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPartialHistories)
      25           0 :   for (GroupedSHistory::PrerenderingHistory& h : tmp->mPrerenderingHistories) {
      26           0 :     ImplCycleCollectionTraverse(cb, h.mPartialHistory, "mPrerenderingHistories[i]->mPartialHistory", 0);
      27             :   }
      28           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
      29             : 
      30           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(GroupedSHistory)
      31           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(GroupedSHistory)
      32             : 
      33           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(GroupedSHistory)
      34           0 :   NS_INTERFACE_MAP_ENTRY(nsIGroupedSHistory)
      35           0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIGroupedSHistory)
      36           0 : NS_INTERFACE_MAP_END
      37             : 
      38           0 : GroupedSHistory::GroupedSHistory()
      39             :   : mCount(0),
      40           0 :     mIndexOfActivePartialHistory(-1)
      41             : {
      42           0 : }
      43             : 
      44             : NS_IMETHODIMP
      45           0 : GroupedSHistory::GetCount(uint32_t* aResult)
      46             : {
      47           0 :   MOZ_ASSERT(aResult);
      48           0 :   *aResult = mCount;
      49           0 :   return NS_OK;
      50             : }
      51             : 
      52             : NS_IMETHODIMP
      53           0 : GroupedSHistory::AppendPartialSHistory(nsIPartialSHistory* aPartialHistory)
      54             : {
      55           0 :   if (!aPartialHistory) {
      56           0 :     return NS_ERROR_INVALID_POINTER;
      57             :   }
      58             : 
      59           0 :   nsCOMPtr<nsIPartialSHistory> partialHistory(aPartialHistory);
      60           0 :   if (!partialHistory || mPartialHistories.Contains(partialHistory)) {
      61           0 :     return NS_ERROR_FAILURE;
      62             :   }
      63             : 
      64             :   // Remove all items after active one and deactive it, unless it's the first
      65             :   // call and no active partial history has been set yet.
      66           0 :   if (mIndexOfActivePartialHistory >= 0) {
      67           0 :     PurgePartialHistories(mIndexOfActivePartialHistory);
      68             :     nsCOMPtr<nsIPartialSHistory> prevPartialHistory =
      69           0 :       mPartialHistories[mIndexOfActivePartialHistory];
      70           0 :     if (NS_WARN_IF(!prevPartialHistory)) {
      71             :       // Cycle collected?
      72           0 :       return NS_ERROR_UNEXPECTED;
      73             :     }
      74           0 :     prevPartialHistory->OnDeactive();
      75             :   }
      76             : 
      77             :   // Attach the partial history.
      78           0 :   uint32_t offset = mCount;
      79           0 :   mCount += partialHistory->GetCount();
      80           0 :   mPartialHistories.AppendElement(partialHistory);
      81           0 :   partialHistory->OnAttachGroupedSHistory(this, offset);
      82           0 :   mIndexOfActivePartialHistory = mPartialHistories.Count() - 1;
      83             : 
      84             :   // Remove the prerendered documents, as there was a history navigation
      85           0 :   PurgePrerendering();
      86             : 
      87           0 :   return NS_OK;
      88             : }
      89             : 
      90             : NS_IMETHODIMP
      91           0 : GroupedSHistory::HandleSHistoryUpdate(nsIPartialSHistory* aPartial, bool aTruncate)
      92             : {
      93           0 :   if (!aPartial) {
      94           0 :     return NS_ERROR_INVALID_POINTER;
      95             :   }
      96           0 :   nsCOMPtr<nsIPartialSHistory> partialHistory = aPartial;
      97             : 
      98           0 :   int32_t index = partialHistory->GetGlobalIndex();
      99             :   // Get the lower and upper bounds for the viewer window
     100           0 :   int32_t lower = index - nsISHistory::VIEWER_WINDOW;
     101           0 :   int32_t upper = index + nsISHistory::VIEWER_WINDOW;
     102           0 :   for (uint32_t i = 0; i < mPartialHistories.Length(); ++i) {
     103           0 :     nsIPartialSHistory* pHistory = mPartialHistories[i];
     104             :     // Skip the active partial history.
     105           0 :     if (pHistory == partialHistory) {
     106           0 :       continue;
     107             :     }
     108             : 
     109             :     // Check if the given partialshistory entry is too far away in history, and
     110             :     // if it is, close it.
     111           0 :     int32_t thisCount = pHistory->GetCount();
     112           0 :     int32_t thisOffset = pHistory->GetGlobalIndexOffset();
     113           0 :     if ((thisOffset > upper) || ((thisCount + thisOffset) < lower)) {
     114           0 :       nsCOMPtr<nsIFrameLoader> loader;
     115           0 :       pHistory->GetOwnerFrameLoader(getter_AddRefs(loader));
     116           0 :       if (loader && !loader->GetIsDead()) {
     117           0 :         loader->RequestFrameLoaderClose();
     118             :       }
     119             :     }
     120             :   }
     121             : 
     122             :   // Remove the prerendered documents, as there was a history navigation
     123           0 :   PurgePrerendering();
     124             : 
     125             :   // If we should be truncating, make sure to purge any partialSHistories which
     126             :   // follow the one being updated.
     127           0 :   if (aTruncate) {
     128           0 :     int32_t index = mPartialHistories.IndexOf(partialHistory);
     129           0 :     if (NS_WARN_IF(index != mIndexOfActivePartialHistory) ||
     130           0 :         NS_WARN_IF(index < 0)) {
     131             :       // Non-active or not attached partialHistory
     132           0 :       return NS_ERROR_UNEXPECTED;
     133             :     }
     134             : 
     135           0 :     PurgePartialHistories(index);
     136             : 
     137             :     // Update global count.
     138           0 :     uint32_t count = partialHistory->GetCount();
     139           0 :     uint32_t offset = partialHistory->GetGlobalIndexOffset();
     140           0 :     mCount = count + offset;
     141             :   }
     142             : 
     143           0 :   return NS_OK;
     144             : }
     145             : 
     146             : NS_IMETHODIMP
     147           0 : GroupedSHistory::GotoIndex(uint32_t aGlobalIndex,
     148             :                            nsIFrameLoader** aTargetLoaderToSwap)
     149             : {
     150           0 :   MOZ_ASSERT(aTargetLoaderToSwap);
     151           0 :   *aTargetLoaderToSwap = nullptr;
     152             : 
     153             :   nsCOMPtr<nsIPartialSHistory> currentPartialHistory =
     154           0 :     mPartialHistories[mIndexOfActivePartialHistory];
     155           0 :   if (!currentPartialHistory) {
     156             :     // Cycle collected?
     157           0 :     return NS_ERROR_UNEXPECTED;
     158             :   }
     159             : 
     160           0 :   for (uint32_t i = 0; i < mPartialHistories.Length(); i++) {
     161           0 :     nsCOMPtr<nsIPartialSHistory> partialHistory = mPartialHistories[i];
     162           0 :     if (NS_WARN_IF(!partialHistory)) {
     163             :       // Cycle collected?
     164           0 :       return NS_ERROR_UNEXPECTED;
     165             :     }
     166             : 
     167             :     // Examine index range.
     168           0 :     uint32_t offset = partialHistory->GetGlobalIndexOffset();
     169           0 :     uint32_t count = partialHistory->GetCount();
     170           0 :     if (offset <= aGlobalIndex && (offset + count) > aGlobalIndex) {
     171           0 :       uint32_t targetIndex = aGlobalIndex - offset;
     172             : 
     173             :       // Check if we are trying to swap to a dead frameloader, and return
     174             :       // NS_ERROR_NOT_AVAILABLE if we are.
     175           0 :       nsCOMPtr<nsIFrameLoader> frameLoader;
     176           0 :       partialHistory->GetOwnerFrameLoader(getter_AddRefs(frameLoader));
     177           0 :       if (!frameLoader || frameLoader->GetIsDead()) {
     178           0 :         return NS_ERROR_NOT_AVAILABLE;
     179             :       }
     180             : 
     181           0 :       if ((size_t)mIndexOfActivePartialHistory == i) {
     182           0 :         return NS_OK;
     183             :       }
     184           0 :       mIndexOfActivePartialHistory = i;
     185           0 :       if (NS_FAILED(currentPartialHistory->OnDeactive()) ||
     186           0 :           NS_FAILED(partialHistory->OnActive(mCount, targetIndex))) {
     187           0 :         return NS_ERROR_FAILURE;
     188             :       }
     189             : 
     190             :       // Return the target frameloader to the caller.
     191           0 :       frameLoader.forget(aTargetLoaderToSwap);
     192           0 :       return NS_OK;
     193             :     }
     194             :   }
     195             : 
     196             :   // Index not found.
     197           0 :   NS_WARNING("Out of index request!");
     198           0 :   return NS_ERROR_FAILURE;
     199             : }
     200             : 
     201             : void
     202           0 : GroupedSHistory::PurgePartialHistories(uint32_t aLastPartialIndexToKeep)
     203             : {
     204           0 :   uint32_t lastIndex = mPartialHistories.Length() - 1;
     205           0 :   if (aLastPartialIndexToKeep >= lastIndex) {
     206             :     // Nothing to remove.
     207           0 :     return;
     208             :   }
     209             : 
     210             :   // Close tabs.
     211           0 :   for (uint32_t i = lastIndex; i > aLastPartialIndexToKeep; i--) {
     212           0 :     nsCOMPtr<nsIPartialSHistory> partialHistory = mPartialHistories[i];
     213           0 :     if (!partialHistory) {
     214             :       // Cycle collected?
     215           0 :       return;
     216             :     }
     217             : 
     218           0 :     nsCOMPtr<nsIFrameLoader> loader;
     219           0 :     partialHistory->GetOwnerFrameLoader(getter_AddRefs(loader));
     220           0 :     loader->RequestFrameLoaderClose();
     221             :   }
     222             : 
     223             :   // Remove references.
     224           0 :   mPartialHistories.RemoveElementsAt(aLastPartialIndexToKeep + 1,
     225           0 :                                      lastIndex - aLastPartialIndexToKeep);
     226             : }
     227             : 
     228             : /* static */ bool
     229           2 : GroupedSHistory::GroupedHistoryEnabled() {
     230             :   static bool sGroupedSHistoryEnabled = false;
     231             :   static bool sGroupedSHistoryPrefCached = false;
     232           2 :   if (!sGroupedSHistoryPrefCached) {
     233           2 :     sGroupedSHistoryPrefCached = true;
     234             :     Preferences::AddBoolVarCache(&sGroupedSHistoryEnabled,
     235             :                                  "browser.groupedhistory.enabled",
     236           2 :                                  false);
     237             :   }
     238             : 
     239           2 :   return sGroupedSHistoryEnabled;
     240             : }
     241             : 
     242             : void
     243           0 : GroupedSHistory::PurgePrerendering()
     244             : {
     245           0 :   nsTArray<PrerenderingHistory> histories = Move(mPrerenderingHistories);
     246             :   // Remove the frameloaders which are owned by the prerendering history, and
     247             :   // remove them from mPrerenderingHistories.
     248           0 :   for (uint32_t i = 0; i < histories.Length(); ++i) {
     249           0 :     nsCOMPtr<nsIFrameLoader> loader;
     250           0 :     histories[i].mPartialHistory->GetOwnerFrameLoader(getter_AddRefs(loader));
     251           0 :     if (loader) {
     252           0 :       loader->RequestFrameLoaderClose();
     253             :     }
     254             :   }
     255           0 :   MOZ_ASSERT(mPrerenderingHistories.IsEmpty());
     256           0 : }
     257             : 
     258             : NS_IMETHODIMP
     259           0 : GroupedSHistory::CloseInactiveFrameLoaderOwners()
     260             : {
     261           0 :   MOZ_ASSERT(mIndexOfActivePartialHistory >= 0);
     262             :   // Remove inactive frameloaders which are participating in the grouped shistory
     263           0 :   for (uint32_t i = 0; i < mPartialHistories.Length(); ++i) {
     264           0 :     if (i != static_cast<uint32_t>(mIndexOfActivePartialHistory)) {
     265           0 :       nsCOMPtr<nsIFrameLoader> loader;
     266           0 :       mPartialHistories[i]->GetOwnerFrameLoader(getter_AddRefs(loader));
     267           0 :       loader->RequestFrameLoaderClose();
     268             :     }
     269             :   }
     270             : 
     271           0 :   PurgePrerendering();
     272             : 
     273           0 :   return NS_OK;
     274             : }
     275             : 
     276             : NS_IMETHODIMP
     277           0 : GroupedSHistory::AddPrerenderingPartialSHistory(nsIPartialSHistory* aPrerendering, int32_t aId)
     278             : {
     279           0 :   NS_ENSURE_TRUE(aPrerendering && aId, NS_ERROR_UNEXPECTED);
     280           0 :   aPrerendering->SetActiveState(nsIPartialSHistory::STATE_PRERENDER);
     281           0 :   PrerenderingHistory history = { aPrerendering, aId };
     282           0 :   mPrerenderingHistories.AppendElement(history);
     283           0 :   return NS_OK;
     284             : }
     285             : 
     286             : NS_IMETHODIMP
     287           0 : GroupedSHistory::GetActiveFrameLoader(nsIFrameLoader** aFrameLoader)
     288             : {
     289           0 :   if (mIndexOfActivePartialHistory >= 0) {
     290           0 :     return mPartialHistories[mIndexOfActivePartialHistory]->GetOwnerFrameLoader(aFrameLoader);
     291             :   }
     292           0 :   return NS_ERROR_NOT_AVAILABLE;
     293             : }
     294             : 
     295             : NS_IMETHODIMP
     296           0 : GroupedSHistory::ActivatePrerendering(int32_t aId, JSContext* aCx, nsISupports** aPromise)
     297             : {
     298           0 :   NS_ENSURE_TRUE(aId && aCx && aPromise, NS_ERROR_UNEXPECTED);
     299             : 
     300             :   // Look for an entry with the given aId in mPrerenderingHistories.
     301           0 :   for (uint32_t i = 0; i < mPrerenderingHistories.Length(); ++i) {
     302           0 :     if (mPrerenderingHistories[i].mId == aId) {
     303           0 :       nsCOMPtr<nsIPartialSHistory> partialHistory = mPrerenderingHistories[i].mPartialHistory;
     304           0 :       mPrerenderingHistories.RemoveElementAt(i);
     305             : 
     306           0 :       nsCOMPtr<nsIFrameLoader> fl;
     307           0 :       partialHistory->GetOwnerFrameLoader(getter_AddRefs(fl));
     308           0 :       NS_ENSURE_TRUE(fl, NS_ERROR_FAILURE);
     309             : 
     310           0 :       nsCOMPtr<nsIFrameLoader> activeFl;
     311           0 :       GetActiveFrameLoader(getter_AddRefs(activeFl));
     312           0 :       NS_ENSURE_TRUE(activeFl, NS_ERROR_FAILURE);
     313             : 
     314           0 :       nsresult rv = fl->MakePrerenderedLoaderActive();
     315           0 :       NS_ENSURE_SUCCESS(rv, rv);
     316             : 
     317           0 :       return activeFl->AppendPartialSHistoryAndSwap(fl, aPromise);
     318             :     }
     319             :   }
     320             : 
     321             :   // Generate a rejected promise as the entry was not found.
     322           0 :   nsCOMPtr<nsIGlobalObject> go = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx));
     323           0 :   if (NS_WARN_IF(!go)) {
     324           0 :     return NS_ERROR_FAILURE;
     325             :   }
     326           0 :   ErrorResult rv;
     327           0 :   RefPtr<Promise> promise = Promise::Reject(go, aCx, JS::UndefinedHandleValue, rv);
     328           0 :   if (NS_WARN_IF(rv.Failed())) {
     329           0 :     return NS_ERROR_FAILURE;
     330             :   }
     331           0 :   promise.forget(aPromise);
     332           0 :   return NS_OK;
     333             : }
     334             : 
     335             : NS_IMETHODIMP
     336           0 : GroupedSHistory::CancelPrerendering(int32_t aId)
     337             : {
     338           0 :   for (uint32_t i = 0; i < mPrerenderingHistories.Length(); ++i) {
     339           0 :     if (mPrerenderingHistories[i].mId == aId) {
     340           0 :       nsCOMPtr<nsIPartialSHistory> partialHistory = mPrerenderingHistories[i].mPartialHistory;
     341           0 :       nsCOMPtr<nsIFrameLoader> fl;
     342           0 :       partialHistory->GetOwnerFrameLoader(getter_AddRefs(fl));
     343           0 :       if (fl) {
     344           0 :         fl->RequestFrameLoaderClose();
     345             :       }
     346           0 :       mPrerenderingHistories.RemoveElementAt(i);
     347             :     }
     348             :   }
     349             : 
     350           0 :   return NS_OK;
     351             : }
     352             : 
     353             : } // namespace dom
     354           9 : } // namespace mozilla

Generated by: LCOV version 1.13