forked from mirrors/gecko-dev
Bug 1347823 - Part 2: Move HistoryTracker to nsSHistory and bind its event target to the TabGroup. r=smaug
Convert the singleton HistoryTracker implementation to a per-nsSHistory based implementation so that it can be bound to a TabGroup. MozReview-Commit-ID: 7cMtArsO5lQ --HG-- extra : rebase_source : 3711bc7f7afaa40772035e24270d4fde1d17924a
This commit is contained in:
parent
c88a3d7711
commit
ada8242de0
7 changed files with 120 additions and 88 deletions
|
|
@ -21,6 +21,7 @@ interface nsIDocShellTreeItem;
|
|||
interface nsIStructuredCloneContainer;
|
||||
interface nsIBFCacheEntry;
|
||||
interface nsIPrincipal;
|
||||
interface nsISHistory;
|
||||
|
||||
%{C++
|
||||
#include "nsRect.h"
|
||||
|
|
@ -326,6 +327,11 @@ interface nsISHEntry : nsISupports
|
|||
* if true == "manual", false == "auto".
|
||||
*/
|
||||
attribute boolean scrollRestorationIsManual;
|
||||
|
||||
/**
|
||||
* Set the session history it belongs to. It's only set on root entries.
|
||||
*/
|
||||
[noscript] void setSHistory(in nsISHistory aSHistory);
|
||||
};
|
||||
|
||||
[scriptable, uuid(bb66ac35-253b-471f-a317-3ece940f04c5)]
|
||||
|
|
|
|||
|
|
@ -96,6 +96,16 @@ interface nsISHistoryInternal: nsISupports
|
|||
*/
|
||||
void evictAllContentViewers();
|
||||
|
||||
/**
|
||||
* Add a BFCache entry to expiration tracker so it gets evicted on expiration.
|
||||
*/
|
||||
void addToExpirationTracker(in nsIBFCacheEntry aEntry);
|
||||
|
||||
/**
|
||||
* Remove a BFCache entry from expiration tracker.
|
||||
*/
|
||||
void removeFromExpirationTracker(in nsIBFCacheEntry aEntry);
|
||||
|
||||
/**
|
||||
* Remove dynamic entries found at given index.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -962,3 +962,10 @@ nsSHEntry::SetLastTouched(uint32_t aLastTouched)
|
|||
mShared->mLastTouched = aLastTouched;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHEntry::SetSHistory(nsISHistory* aSHistory)
|
||||
{
|
||||
mShared->mSHistory = do_GetWeakReference(aSHistory);
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,46 +30,9 @@ uint64_t gSHEntrySharedID = 0;
|
|||
|
||||
} // namespace
|
||||
|
||||
#define CONTENT_VIEWER_TIMEOUT_SECONDS "browser.sessionhistory.contentViewerTimeout"
|
||||
// Default this to time out unused content viewers after 30 minutes
|
||||
#define CONTENT_VIEWER_TIMEOUT_SECONDS_DEFAULT (30 * 60)
|
||||
|
||||
typedef nsExpirationTracker<nsSHEntryShared, 3> HistoryTrackerBase;
|
||||
class HistoryTracker final : public HistoryTrackerBase
|
||||
{
|
||||
public:
|
||||
explicit HistoryTracker(uint32_t aTimeout)
|
||||
: HistoryTrackerBase(1000 * aTimeout / 2, "HistoryTracker")
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void NotifyExpired(nsSHEntryShared* aObj)
|
||||
{
|
||||
RemoveObject(aObj);
|
||||
aObj->Expire();
|
||||
}
|
||||
};
|
||||
|
||||
static HistoryTracker* gHistoryTracker = nullptr;
|
||||
|
||||
void
|
||||
nsSHEntryShared::EnsureHistoryTracker()
|
||||
{
|
||||
if (!gHistoryTracker) {
|
||||
// nsExpirationTracker doesn't allow one to change the timer period,
|
||||
// so just set it once when the history tracker is used for the first time.
|
||||
gHistoryTracker = new HistoryTracker(
|
||||
mozilla::Preferences::GetUint(CONTENT_VIEWER_TIMEOUT_SECONDS,
|
||||
CONTENT_VIEWER_TIMEOUT_SECONDS_DEFAULT));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsSHEntryShared::Shutdown()
|
||||
{
|
||||
delete gHistoryTracker;
|
||||
gHistoryTracker = nullptr;
|
||||
}
|
||||
|
||||
nsSHEntryShared::nsSHEntryShared()
|
||||
|
|
@ -88,20 +51,6 @@ nsSHEntryShared::nsSHEntryShared()
|
|||
nsSHEntryShared::~nsSHEntryShared()
|
||||
{
|
||||
RemoveFromExpirationTracker();
|
||||
|
||||
#ifdef DEBUG
|
||||
if (gHistoryTracker) {
|
||||
// Check that we're not still on track to expire. We shouldn't be, because
|
||||
// we just removed ourselves!
|
||||
nsExpirationTracker<nsSHEntryShared, 3>::Iterator iterator(gHistoryTracker);
|
||||
|
||||
nsSHEntryShared* elem;
|
||||
while ((elem = iterator.Next()) != nullptr) {
|
||||
NS_ASSERTION(elem != this, "Found dead entry still in the tracker!");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mContentViewer) {
|
||||
RemoveFromBFCacheSync();
|
||||
}
|
||||
|
|
@ -132,8 +81,9 @@ nsSHEntryShared::Duplicate(nsSHEntryShared* aEntry)
|
|||
void
|
||||
nsSHEntryShared::RemoveFromExpirationTracker()
|
||||
{
|
||||
if (gHistoryTracker && GetExpirationState()->IsTracked()) {
|
||||
gHistoryTracker->RemoveObject(this);
|
||||
nsCOMPtr<nsISHistoryInternal> shistory = do_QueryReferent(mSHistory);
|
||||
if (shistory && GetExpirationState()->IsTracked()) {
|
||||
shistory->RemoveFromExpirationTracker(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -174,34 +124,6 @@ nsSHEntryShared::DropPresentationState()
|
|||
mEditorData = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
nsSHEntryShared::Expire()
|
||||
{
|
||||
// This entry has timed out. If we still have a content viewer, we need to
|
||||
// evict it.
|
||||
if (!mContentViewer) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIDocShell> container;
|
||||
mContentViewer->GetContainer(getter_AddRefs(container));
|
||||
nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(container);
|
||||
if (!treeItem) {
|
||||
return;
|
||||
}
|
||||
// We need to find the root DocShell since only that object has an
|
||||
// SHistory and we need the SHistory to evict content viewers
|
||||
nsCOMPtr<nsIDocShellTreeItem> root;
|
||||
treeItem->GetSameTypeRootTreeItem(getter_AddRefs(root));
|
||||
nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(root);
|
||||
nsCOMPtr<nsISHistory> history;
|
||||
webNav->GetSessionHistory(getter_AddRefs(history));
|
||||
nsCOMPtr<nsISHistoryInternal> historyInt = do_QueryInterface(history);
|
||||
if (!historyInt) {
|
||||
return;
|
||||
}
|
||||
historyInt->EvictExpiredContentViewerForEntry(this);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSHEntryShared::SetContentViewer(nsIContentViewer* aViewer)
|
||||
{
|
||||
|
|
@ -215,8 +137,13 @@ nsSHEntryShared::SetContentViewer(nsIContentViewer* aViewer)
|
|||
mContentViewer = aViewer;
|
||||
|
||||
if (mContentViewer) {
|
||||
EnsureHistoryTracker();
|
||||
gHistoryTracker->AddObject(this);
|
||||
// mSHistory is only set for root entries, but in general bfcache only
|
||||
// applies to root entries as well. BFCache for subframe navigation has been
|
||||
// disabled since 2005 in bug 304860.
|
||||
nsCOMPtr<nsISHistoryInternal> shistory = do_QueryReferent(mSHistory);
|
||||
if (shistory) {
|
||||
shistory->AddToExpirationTracker(this);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
mContentViewer->GetDOMDocument(getter_AddRefs(domDoc));
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include "nsIMutationObserver.h"
|
||||
#include "nsRect.h"
|
||||
#include "nsString.h"
|
||||
#include "nsWeakPtr.h"
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
|
|
@ -54,12 +55,9 @@ private:
|
|||
|
||||
friend class nsSHEntry;
|
||||
|
||||
friend class HistoryTracker;
|
||||
|
||||
static already_AddRefed<nsSHEntryShared> Duplicate(nsSHEntryShared* aEntry);
|
||||
|
||||
void RemoveFromExpirationTracker();
|
||||
void Expire();
|
||||
nsresult SyncPresentationState();
|
||||
void DropPresentationState();
|
||||
|
||||
|
|
@ -89,11 +87,14 @@ private:
|
|||
nsCOMPtr<nsIMutableArray> mRefreshURIList;
|
||||
nsExpirationState mExpirationState;
|
||||
nsAutoPtr<nsDocShellEditorData> mEditorData;
|
||||
nsWeakPtr mSHistory;
|
||||
|
||||
bool mIsFrameNavigation;
|
||||
bool mSaveLayoutState;
|
||||
bool mSticky;
|
||||
bool mDynamicallyCreated;
|
||||
|
||||
// This flag is about necko cache, not bfcache.
|
||||
bool mExpired;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -32,11 +32,16 @@
|
|||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/dom/TabGroup.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
#define PREF_SHISTORY_SIZE "browser.sessionhistory.max_entries"
|
||||
#define PREF_SHISTORY_MAX_TOTAL_VIEWERS "browser.sessionhistory.max_total_viewers"
|
||||
#define CONTENT_VIEWER_TIMEOUT_SECONDS "browser.sessionhistory.contentViewerTimeout"
|
||||
|
||||
// Default this to time out unused content viewers after 30 minutes
|
||||
#define CONTENT_VIEWER_TIMEOUT_SECONDS_DEFAULT (30 * 60)
|
||||
|
||||
static const char* kObservedPrefs[] = {
|
||||
PREF_SHISTORY_SIZE,
|
||||
|
|
@ -251,6 +256,7 @@ NS_INTERFACE_MAP_BEGIN(nsSHistory)
|
|||
NS_INTERFACE_MAP_ENTRY(nsISHistory)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIWebNavigation)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISHistoryInternal)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
// static
|
||||
|
|
@ -379,6 +385,8 @@ nsSHistory::AddEntry(nsISHEntry* aSHEntry, bool aPersist)
|
|||
{
|
||||
NS_ENSURE_ARG(aSHEntry);
|
||||
|
||||
aSHEntry->SetSHistory(this);
|
||||
|
||||
// If we have a root docshell, update the docshell id of the root shentry to
|
||||
// match the id of that docshell
|
||||
if (mRootDocShell) {
|
||||
|
|
@ -1296,6 +1304,30 @@ nsSHistory::EvictExpiredContentViewerForEntry(nsIBFCacheEntry* aEntry)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHistory::AddToExpirationTracker(nsIBFCacheEntry* aEntry)
|
||||
{
|
||||
RefPtr<nsSHEntryShared> entry = static_cast<nsSHEntryShared*>(aEntry);
|
||||
if (!mHistoryTracker || !entry) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mHistoryTracker->AddObject(entry);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHistory::RemoveFromExpirationTracker(nsIBFCacheEntry* aEntry)
|
||||
{
|
||||
RefPtr<nsSHEntryShared> entry = static_cast<nsSHEntryShared*>(aEntry);
|
||||
if (!mHistoryTracker || !entry) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mHistoryTracker->RemoveObject(entry);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Evicts all content viewers in all history objects. This is very
|
||||
// inefficient, because it requires a linear search through all SHistory
|
||||
// objects for each viewer to be evicted. However, this method is called
|
||||
|
|
@ -1896,6 +1928,23 @@ NS_IMETHODIMP
|
|||
nsSHistory::SetRootDocShell(nsIDocShell* aDocShell)
|
||||
{
|
||||
mRootDocShell = aDocShell;
|
||||
|
||||
// Init mHistoryTracker on setting mRootDocShell so we can bind its event
|
||||
// target to the tabGroup.
|
||||
if (mRootDocShell) {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> win = mRootDocShell->GetWindow();
|
||||
if (!win) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
RefPtr<mozilla::dom::TabGroup> tabGroup = win->TabGroup();
|
||||
mHistoryTracker = mozilla::MakeUnique<HistoryTracker>(
|
||||
this,
|
||||
mozilla::Preferences::GetUint(CONTENT_VIEWER_TIMEOUT_SECONDS,
|
||||
CONTENT_VIEWER_TIMEOUT_SECONDS_DEFAULT),
|
||||
tabGroup->EventTargetFor(mozilla::TaskCategory::Other));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,9 +16,10 @@
|
|||
#include "nsIWebNavigation.h"
|
||||
#include "nsSHEntryShared.h"
|
||||
#include "nsTObserverArray.h"
|
||||
#include "nsWeakPtr.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
class nsIDocShell;
|
||||
class nsSHEnumerator;
|
||||
|
|
@ -29,9 +30,37 @@ class nsISHTransaction;
|
|||
class nsSHistory final : public mozilla::LinkedListElement<nsSHistory>,
|
||||
public nsISHistory,
|
||||
public nsISHistoryInternal,
|
||||
public nsIWebNavigation
|
||||
public nsIWebNavigation,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
|
||||
// The timer based history tracker is used to evict bfcache on expiration.
|
||||
class HistoryTracker final : public nsExpirationTracker<nsSHEntryShared, 3>
|
||||
{
|
||||
public:
|
||||
explicit HistoryTracker(nsSHistory* aSHistory,
|
||||
uint32_t aTimeout,
|
||||
nsIEventTarget* aEventTarget)
|
||||
: nsExpirationTracker(1000 * aTimeout / 2, "HistoryTracker", aEventTarget)
|
||||
{
|
||||
MOZ_ASSERT(aSHistory);
|
||||
mSHistory = aSHistory;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void NotifyExpired(nsSHEntryShared* aObj)
|
||||
{
|
||||
RemoveObject(aObj);
|
||||
mSHistory->EvictExpiredContentViewerForEntry(aObj);
|
||||
}
|
||||
|
||||
private:
|
||||
// HistoryTracker is owned by nsSHistory; it always outlives HistoryTracker
|
||||
// so it's safe to use raw pointer here.
|
||||
nsSHistory* mSHistory;
|
||||
};
|
||||
|
||||
nsSHistory();
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISHISTORY
|
||||
|
|
@ -87,6 +116,9 @@ private:
|
|||
// otherwise comparison is done to aIndex - 1.
|
||||
bool RemoveDuplicate(int32_t aIndex, bool aKeepNext);
|
||||
|
||||
// Track all bfcache entries and evict on expiration.
|
||||
mozilla::UniquePtr<HistoryTracker> mHistoryTracker;
|
||||
|
||||
nsCOMPtr<nsISHTransaction> mListRoot;
|
||||
int32_t mIndex;
|
||||
int32_t mLength;
|
||||
|
|
|
|||
Loading…
Reference in a new issue