зеркало из https://github.com/mozilla/gecko-dev.git
Bug 894215 part 3. Make sure we don't bfcache pages that get mutated after we capture their state. r=smaug
This commit is contained in:
Родитель
6f273bf6d2
Коммит
69f3dde06c
|
@ -26,6 +26,7 @@
|
|||
#include "nsIWritablePropertyBag2.h"
|
||||
#include "nsSubDocumentFrame.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "nsStubMutationObserver.h"
|
||||
|
||||
#include "nsILinkHandler.h"
|
||||
#include "nsISelectionListener.h"
|
||||
|
@ -203,6 +204,108 @@ private:
|
|||
nsDocumentViewer* mDocViewer;
|
||||
};
|
||||
|
||||
namespace viewer_detail {
|
||||
|
||||
/**
|
||||
* Mutation observer for use until we hand ourselves over to our SHEntry.
|
||||
*/
|
||||
class BFCachePreventionObserver final : public nsStubMutationObserver
|
||||
{
|
||||
public:
|
||||
explicit BFCachePreventionObserver(nsIDocument* aDocument)
|
||||
: mDocument(aDocument)
|
||||
{
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
|
||||
|
||||
// Stop observing the document.
|
||||
void Disconnect();
|
||||
|
||||
private:
|
||||
~BFCachePreventionObserver() = default;
|
||||
|
||||
// Helper for the work that needs to happen when mutations happen.
|
||||
void MutationHappened();
|
||||
|
||||
nsIDocument* mDocument; // Weak; we get notified if it dies
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(BFCachePreventionObserver, nsIMutationObserver)
|
||||
|
||||
void
|
||||
BFCachePreventionObserver::CharacterDataChanged(nsIContent* aContent,
|
||||
const CharacterDataChangeInfo&)
|
||||
{
|
||||
MutationHappened();
|
||||
}
|
||||
|
||||
void
|
||||
BFCachePreventionObserver::AttributeChanged(Element* aElement,
|
||||
int32_t aNameSpaceID,
|
||||
nsAtom* aAttribute,
|
||||
int32_t aModType,
|
||||
const nsAttrValue* aOldValue)
|
||||
{
|
||||
MutationHappened();
|
||||
}
|
||||
|
||||
void
|
||||
BFCachePreventionObserver::ContentAppended(nsIContent* aFirstNewContent)
|
||||
{
|
||||
MutationHappened();
|
||||
}
|
||||
|
||||
void
|
||||
BFCachePreventionObserver::ContentInserted(nsIContent* aChild)
|
||||
{
|
||||
MutationHappened();
|
||||
}
|
||||
|
||||
void
|
||||
BFCachePreventionObserver::ContentRemoved(nsIContent* aChild,
|
||||
nsIContent* aPreviousSibling)
|
||||
{
|
||||
MutationHappened();
|
||||
}
|
||||
|
||||
void
|
||||
BFCachePreventionObserver::NodeWillBeDestroyed(const nsINode* aNode)
|
||||
{
|
||||
mDocument = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
BFCachePreventionObserver::Disconnect()
|
||||
{
|
||||
if (mDocument) {
|
||||
mDocument->RemoveMutationObserver(this);
|
||||
// It will no longer tell us when it goes away, so make sure we're
|
||||
// not holding a dangling ref.
|
||||
mDocument = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BFCachePreventionObserver::MutationHappened()
|
||||
{
|
||||
MOZ_ASSERT(mDocument,
|
||||
"How can we not have a document but be getting notified for mutations?");
|
||||
mDocument->DisallowBFCaching();
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
|
||||
} // namespace viewer_detail
|
||||
|
||||
using viewer_detail::BFCachePreventionObserver;
|
||||
|
||||
//-------------------------------------------------------------
|
||||
class nsDocumentViewer final : public nsIContentViewer,
|
||||
|
@ -340,6 +443,9 @@ protected:
|
|||
|
||||
nsCOMPtr<nsIContentViewer> mPreviousViewer;
|
||||
nsCOMPtr<nsISHEntry> mSHEntry;
|
||||
// Observer that will prevent bfcaching if it gets notified. This
|
||||
// is non-null precisely when mSHEntry is non-null.
|
||||
RefPtr<BFCachePreventionObserver> mBFCachePreventionObserver;
|
||||
|
||||
nsIWidget* mParentWidget; // purposely won't be ref counted. May be null
|
||||
bool mAttachedToParent; // view is attached to the parent widget
|
||||
|
@ -1562,6 +1668,14 @@ nsDocumentViewer::Close(nsISHEntry *aSHEntry)
|
|||
if (!mDocument)
|
||||
return NS_OK;
|
||||
|
||||
if (mSHEntry) {
|
||||
if (mBFCachePreventionObserver) {
|
||||
mBFCachePreventionObserver->Disconnect();
|
||||
}
|
||||
mBFCachePreventionObserver = new BFCachePreventionObserver(mDocument);
|
||||
mDocument->AddMutationObserver(mBFCachePreventionObserver);
|
||||
}
|
||||
|
||||
#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
|
||||
// Turn scripting back on
|
||||
// after PrintPreview had turned it off
|
||||
|
@ -1664,6 +1778,13 @@ nsDocumentViewer::Destroy()
|
|||
mAutoBeforeAndAfterPrint = nullptr;
|
||||
#endif
|
||||
|
||||
// We want to make sure to disconnect mBFCachePreventionObserver before we
|
||||
// Sanitize() below.
|
||||
if (mBFCachePreventionObserver) {
|
||||
mBFCachePreventionObserver->Disconnect();
|
||||
mBFCachePreventionObserver = nullptr;
|
||||
}
|
||||
|
||||
if (mSHEntry && mDocument && !mDocument->IsBFCachingAllowed()) {
|
||||
// Just drop the SHEntry now and pretend like we never even tried to bfcache
|
||||
// this viewer. This should only happen when someone calls
|
||||
|
|
Загрузка…
Ссылка в новой задаче