mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Bug 1545474 - Part 3: Test eviction of content viewer entries, r=peterv
Add a new callback to session history listener to listen for content viewers being evicted. Differential Revision: https://phabricator.services.mozilla.com/D32731 --HG-- extra : rebase_source : 29c8e9299af718e75029dfae4e937a3d4f18900d extra : amend_source : 19e679c6d2721dd7e8d7da1ec7af3033439210b4 extra : source : 5e4d0ab9e52ce1e1d1684fdb59534a66e9f9d9b9 extra : histedit_source : 44e9cb7ba0589c79c03b2dc58ec4d0d4c0c98422
This commit is contained in:
parent
bfdcd82cdb
commit
7c10781235
@ -58,7 +58,7 @@ parent:
|
||||
sync Evict(PSHEntry[] entry);
|
||||
sync EnsureCorrectEntryAtCurrIndex(PSHEntry entry);
|
||||
sync EvictContentViewersOrReplaceEntry(nullable PSHEntry newSHEntry, bool replace);
|
||||
|
||||
async NotifyListenersContentViewerEvicted(uint32_t numEvicted);
|
||||
async __delete__();
|
||||
};
|
||||
|
||||
|
@ -53,16 +53,25 @@ void SHEntryChildShared::EvictContentViewers(
|
||||
MOZ_ASSERT(sSHEntryChildSharedTable,
|
||||
"we have content viewers to evict, but the table hasn't been "
|
||||
"initialized yet");
|
||||
uint32_t numEvictedSoFar = 0;
|
||||
for (auto iter = aToEvictSharedStateIDs.begin();
|
||||
iter != aToEvictSharedStateIDs.end(); ++iter) {
|
||||
RefPtr<SHEntryChildShared> shared = sSHEntryChildSharedTable->Get(*iter);
|
||||
MOZ_ASSERT(shared, "shared entry can't be null");
|
||||
nsCOMPtr<nsIContentViewer> viewer = shared->mContentViewer;
|
||||
if (viewer) {
|
||||
numEvictedSoFar++;
|
||||
shared->SetContentViewer(nullptr);
|
||||
shared->SyncPresentationState();
|
||||
viewer->Destroy();
|
||||
}
|
||||
if (std::next(iter) == aToEvictSharedStateIDs.end() &&
|
||||
numEvictedSoFar > 0) {
|
||||
// This is the last shared object, so we should notify our
|
||||
// listeners about any content viewers that were evicted.
|
||||
// It does not matter which shared entry we will use for notifying.
|
||||
shared->NotifyListenersContentViewerEvicted(numEvictedSoFar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,6 +143,13 @@ void SHEntryChildShared::DropPresentationState() {
|
||||
mEditorData = nullptr;
|
||||
}
|
||||
|
||||
void SHEntryChildShared::NotifyListenersContentViewerEvicted(
|
||||
uint32_t aNumEvicted) {
|
||||
if (StaticPrefs::docshell_shistory_testing_bfevict() && mSHistory) {
|
||||
mSHistory->SendNotifyListenersContentViewerEvicted(aNumEvicted);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult SHEntryChildShared::SetContentViewer(nsIContentViewer* aViewer) {
|
||||
MOZ_ASSERT(!aViewer || !mContentViewer,
|
||||
"SHEntryShared already contains viewer");
|
||||
@ -994,6 +1010,7 @@ void SHEntryChild::EvictContentViewer() {
|
||||
if (viewer) {
|
||||
// Drop the presentation state before destroying the viewer, so that
|
||||
// document teardown is able to correctly persist the state.
|
||||
mShared->NotifyListenersContentViewerEvicted();
|
||||
SetContentViewer(nullptr);
|
||||
SyncPresentationState();
|
||||
viewer->Destroy();
|
||||
|
@ -45,6 +45,8 @@ class SHEntryChildShared final : public nsIBFCacheEntry,
|
||||
static void EvictContentViewers(
|
||||
const nsTArray<uint64_t>& aToEvictSharedStateIDs);
|
||||
|
||||
void NotifyListenersContentViewerEvicted(uint32_t aNumEvicted = 1);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIBFCACHEENTRY
|
||||
|
||||
|
@ -239,6 +239,12 @@ bool SHistoryParent::RecvEvict(nsTArray<PSHEntryParent*>&& aEntries) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SHistoryParent::RecvNotifyListenersContentViewerEvicted(
|
||||
uint32_t aNumEvicted) {
|
||||
mHistory->NotifyListenersContentViewerEvicted(aNumEvicted);
|
||||
return true;
|
||||
}
|
||||
|
||||
void LegacySHistory::EvictOutOfRangeWindowContentViewers(int32_t aIndex) {
|
||||
if (aIndex < 0) {
|
||||
return;
|
||||
|
@ -80,6 +80,7 @@ class SHistoryParent final : public PSHistoryParent {
|
||||
bool RecvEvict(nsTArray<PSHEntryParent*>&& aEntries);
|
||||
bool RecvEnsureCorrectEntryAtCurrIndex(PSHEntryParent* aEntry);
|
||||
bool RecvEvictContentViewersOrReplaceEntry(PSHEntryParent* aNewSHEntry, bool aReplace);
|
||||
bool RecvNotifyListenersContentViewerEvicted(uint32_t aNumEvicted);
|
||||
|
||||
RefPtr<CanonicalBrowsingContext> mContext;
|
||||
RefPtr<LegacySHistory> mHistory;
|
||||
|
@ -65,4 +65,14 @@ interface nsISHistoryListener : nsISupports
|
||||
* about pages) and when history.replaceState is called.
|
||||
*/
|
||||
void OnHistoryReplaceEntry();
|
||||
|
||||
|
||||
/**
|
||||
* Called whenever a content viewer is evicted. A content viewer is evicted
|
||||
* whenever a bfcache entry has timed out or the number of total content
|
||||
* viewers has exceeded the global max. This is used for testing only.
|
||||
*
|
||||
* @param aNumEvicted - number of content viewers evicted
|
||||
*/
|
||||
void OnContentViewerEvicted(in unsigned long aNumEvicted);
|
||||
};
|
||||
|
@ -1038,6 +1038,7 @@ nsLegacySHEntry::CreateLoadInfo(nsDocShellLoadState** aLoadState) {
|
||||
void nsSHEntry::EvictContentViewer() {
|
||||
nsCOMPtr<nsIContentViewer> viewer = GetContentViewer();
|
||||
if (viewer) {
|
||||
mShared->NotifyListenersContentViewerEvicted();
|
||||
// Drop the presentation state before destroying the viewer, so that
|
||||
// document teardown is able to correctly persist the state.
|
||||
SetContentViewer(nullptr);
|
||||
|
@ -52,6 +52,13 @@ void dom::SHEntrySharedParentState::CopyFrom(
|
||||
mLastTouched = aEntry->mLastTouched;
|
||||
}
|
||||
|
||||
void dom::SHEntrySharedParentState::NotifyListenersContentViewerEvicted() {
|
||||
if (nsCOMPtr<nsISHistory> shistory = do_QueryReferent(mSHistory)) {
|
||||
RefPtr<nsSHistory> nsshistory = static_cast<nsSHistory*>(shistory.get());
|
||||
nsshistory->NotifyListenersContentViewerEvicted(1);
|
||||
}
|
||||
}
|
||||
|
||||
dom::SHEntrySharedChildState::SHEntrySharedChildState()
|
||||
: mSaveLayoutState(true) {}
|
||||
|
||||
|
@ -51,6 +51,8 @@ class SHEntrySharedParentState {
|
||||
|
||||
uint64_t GetID() const { return mID; }
|
||||
|
||||
void NotifyListenersContentViewerEvicted();
|
||||
|
||||
protected:
|
||||
friend class nsSHEntry;
|
||||
|
||||
|
@ -179,6 +179,7 @@ void nsSHistory::EvictContentViewerForEntry(nsISHEntry* aEntry) {
|
||||
|
||||
// Drop the presentation state before destroying the viewer, so that
|
||||
// document teardown is able to correctly persist the state.
|
||||
NotifyListenersContentViewerEvicted(1);
|
||||
aEntry->SetContentViewer(nullptr);
|
||||
aEntry->SyncPresentationState();
|
||||
viewer->Destroy();
|
||||
@ -745,6 +746,10 @@ nsSHistory::AddSHistoryListener(nsISHistoryListener* aListener) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsSHistory::NotifyListenersContentViewerEvicted(uint32_t aNumEvicted) {
|
||||
NOTIFY_LISTENERS(OnContentViewerEvicted, (aNumEvicted));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSHistory::RemoveSHistoryListener(nsISHistoryListener* aListener) {
|
||||
// Make sure the listener that wants to be removed is the
|
||||
|
@ -143,6 +143,7 @@ class nsSHistory : public mozilla::LinkedListElement<nsSHistory>,
|
||||
|
||||
void WindowIndices(int32_t aIndex, int32_t* aOutStartIndex,
|
||||
int32_t* aOutEndIndex);
|
||||
void NotifyListenersContentViewerEvicted(uint32_t aNumEvicted);
|
||||
|
||||
protected:
|
||||
virtual ~nsSHistory();
|
||||
|
@ -7,6 +7,7 @@ support-files =
|
||||
bug343515_pg3_1_1.html
|
||||
bug343515_pg3_2.html
|
||||
|
||||
[browser_test_bfcache_eviction.js]
|
||||
[browser_bug343515.js]
|
||||
[browser_test-content-chromeflags.js]
|
||||
tags = openwindow
|
||||
|
63
docshell/test/navigation/browser_test_bfcache_eviction.js
Normal file
63
docshell/test/navigation/browser_test_bfcache_eviction.js
Normal file
@ -0,0 +1,63 @@
|
||||
add_task(async function() {
|
||||
// We don't want the number of total viewers to be calculated by the available size
|
||||
// for this test case. Instead, fix the number of viewers.
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
["browser.sessionhistory.max_total_viewers", 3],
|
||||
["docshell.shistory.testing.bfevict", true],
|
||||
],
|
||||
});
|
||||
|
||||
// 1. Open a tab
|
||||
var testPage =
|
||||
"data:text/html,<html id='html1'><body id='body1'></body></html>";
|
||||
await BrowserTestUtils.withNewTab({ gBrowser, url: testPage }, async function(
|
||||
browser
|
||||
) {
|
||||
// 2. Add a promise that will be resolved when the 'content viewer evicted' event goes off
|
||||
let testDone = {};
|
||||
testDone.promise = new Promise(resolve => {
|
||||
testDone.resolve = resolve;
|
||||
});
|
||||
|
||||
let legacySHistory = browser.browsingContext.sessionHistory;
|
||||
// 3. Register a session history listener to listen for a 'content viewer evicted' event.
|
||||
let historyListener = {
|
||||
OnContentViewerEvicted() {
|
||||
ok(
|
||||
true,
|
||||
"History listener got called after a content viewer was evicted"
|
||||
);
|
||||
legacySHistory.removeSHistoryListener(historyListener);
|
||||
// 6. Resolve the promise when we got our 'content viewer evicted' event
|
||||
testDone.resolve();
|
||||
},
|
||||
QueryInterface: ChromeUtils.generateQI([
|
||||
Ci.nsISHistoryListener,
|
||||
Ci.nsISupportsWeakReference,
|
||||
]),
|
||||
};
|
||||
legacySHistory.addSHistoryListener(historyListener);
|
||||
|
||||
// 4. Open a second tab
|
||||
testPage = `data:text/html,<html id='html1'><body id='body1'>I am a second tab!</body></html>`;
|
||||
let tab2 = await BrowserTestUtils.openNewForegroundTab(gBrowser, testPage);
|
||||
|
||||
// 5. Navigate the first tab to 4 different pages.
|
||||
// We should get 1 content viewer evicted because it will be outside of the range.
|
||||
// If we have the following pages in our session history: P1 P2 P3 P4 P5
|
||||
// and we are currently at P5, then P1 is outside of the range
|
||||
// (it is more than 3 entries away from current entry) and thus will be evicted.
|
||||
for (var i = 0; i < 4; i++) {
|
||||
testPage = `data:text/html,<html id='html1'><body id='body1'>${i}</body></html>`;
|
||||
let pagePromise = BrowserTestUtils.browserLoaded(browser);
|
||||
await BrowserTestUtils.loadURI(browser, testPage);
|
||||
await pagePromise;
|
||||
}
|
||||
// 7. Wait for 'content viewer evicted' event to go off
|
||||
await testDone.promise;
|
||||
|
||||
// 8. Close the second tab
|
||||
BrowserTestUtils.removeTab(tab2);
|
||||
});
|
||||
});
|
@ -1234,6 +1234,17 @@
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Prefs starting with "docshell."
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# Used to indicate whether session history listeners should be notified
|
||||
# about content viewer eviction. Used only for testing.
|
||||
- name: docshell.shistory.testing.bfevict
|
||||
type: bool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Prefs starting with "dom."
|
||||
#---------------------------------------------------------------------------
|
||||
|
@ -36,6 +36,7 @@ pref_groups = [
|
||||
'content',
|
||||
'device',
|
||||
'devtools',
|
||||
'docshell',
|
||||
'dom',
|
||||
'editor',
|
||||
'extensions',
|
||||
|
Loading…
Reference in New Issue
Block a user