mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
0be4513261
Differential Revision: https://phabricator.services.mozilla.com/D159237
208 lines
6.8 KiB
C++
208 lines
6.8 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
/*
|
|
* nsStubMutationObserver is an implementation of the nsIMutationObserver
|
|
* interface (except for the methods on nsISupports) that is intended to be
|
|
* used as a base class within the content/layout library. All methods do
|
|
* nothing.
|
|
*/
|
|
|
|
#include "nsStubMutationObserver.h"
|
|
#include "mozilla/RefCountType.h"
|
|
#include "nsISupports.h"
|
|
#include "nsINode.h"
|
|
|
|
/******************************************************************************
|
|
* nsStubMutationObserver
|
|
*****************************************************************************/
|
|
|
|
NS_IMPL_NSIMUTATIONOBSERVER_CORE_STUB(nsStubMutationObserver)
|
|
NS_IMPL_NSIMUTATIONOBSERVER_CONTENT(nsStubMutationObserver)
|
|
|
|
/******************************************************************************
|
|
* MutationObserverWrapper
|
|
*****************************************************************************/
|
|
|
|
/**
|
|
* @brief Wrapper class for a mutation observer that observes multiple nodes.
|
|
*
|
|
* This wrapper implements all methods of the nsIMutationObserver interface
|
|
* and forwards all calls to its owner, which is an instance of
|
|
* nsMultiMutationObserver.
|
|
*
|
|
* This class holds a reference to the owner and AddRefs/Releases its owner
|
|
* as well to ensure lifetime.
|
|
*/
|
|
class MutationObserverWrapper final : public nsIMutationObserver {
|
|
public:
|
|
NS_DECL_ISUPPORTS
|
|
|
|
explicit MutationObserverWrapper(nsMultiMutationObserver* aOwner)
|
|
: mOwner(aOwner) {}
|
|
|
|
void CharacterDataWillChange(nsIContent* aContent,
|
|
const CharacterDataChangeInfo& aInfo) override {
|
|
MOZ_ASSERT(mOwner);
|
|
mOwner->CharacterDataWillChange(aContent, aInfo);
|
|
}
|
|
|
|
void CharacterDataChanged(nsIContent* aContent,
|
|
const CharacterDataChangeInfo& aInfo) override {
|
|
MOZ_ASSERT(mOwner);
|
|
mOwner->CharacterDataChanged(aContent, aInfo);
|
|
}
|
|
|
|
void AttributeWillChange(mozilla::dom::Element* aElement,
|
|
int32_t aNameSpaceID, nsAtom* aAttribute,
|
|
int32_t aModType) override {
|
|
MOZ_ASSERT(mOwner);
|
|
mOwner->AttributeWillChange(aElement, aNameSpaceID, aAttribute, aModType);
|
|
}
|
|
|
|
void AttributeChanged(mozilla::dom::Element* aElement, int32_t aNameSpaceID,
|
|
nsAtom* aAttribute, int32_t aModType,
|
|
const nsAttrValue* aOldValue) override {
|
|
MOZ_ASSERT(mOwner);
|
|
mOwner->AttributeChanged(aElement, aNameSpaceID, aAttribute, aModType,
|
|
aOldValue);
|
|
}
|
|
|
|
void NativeAnonymousChildListChange(nsIContent* aContent,
|
|
bool aIsRemove) override {
|
|
MOZ_ASSERT(mOwner);
|
|
mOwner->NativeAnonymousChildListChange(aContent, aIsRemove);
|
|
}
|
|
|
|
void AttributeSetToCurrentValue(mozilla::dom::Element* aElement,
|
|
int32_t aNameSpaceID,
|
|
nsAtom* aAttribute) override {
|
|
MOZ_ASSERT(mOwner);
|
|
mOwner->AttributeSetToCurrentValue(aElement, aNameSpaceID, aAttribute);
|
|
}
|
|
|
|
void ContentAppended(nsIContent* aFirstNewContent) override {
|
|
MOZ_ASSERT(mOwner);
|
|
mOwner->ContentAppended(aFirstNewContent);
|
|
}
|
|
|
|
void ContentInserted(nsIContent* aChild) override {
|
|
MOZ_ASSERT(mOwner);
|
|
mOwner->ContentInserted(aChild);
|
|
}
|
|
|
|
void ContentRemoved(nsIContent* aChild,
|
|
nsIContent* aPreviousSibling) override {
|
|
MOZ_ASSERT(mOwner);
|
|
mOwner->ContentRemoved(aChild, aPreviousSibling);
|
|
}
|
|
|
|
void NodeWillBeDestroyed(nsINode* aNode) override {
|
|
MOZ_ASSERT(mOwner);
|
|
AddRefWrapper();
|
|
RefPtr<nsMultiMutationObserver> owner = mOwner;
|
|
owner->NodeWillBeDestroyed(aNode);
|
|
owner->RemoveMutationObserverFromNode(aNode);
|
|
mOwner = nullptr;
|
|
ReleaseWrapper();
|
|
}
|
|
|
|
void ParentChainChanged(nsIContent* aContent) override {
|
|
MOZ_ASSERT(mOwner);
|
|
mOwner->ParentChainChanged(aContent);
|
|
}
|
|
|
|
void ARIAAttributeDefaultWillChange(mozilla::dom::Element* aElement,
|
|
nsAtom* aAttribute,
|
|
int32_t aModType) override {
|
|
MOZ_ASSERT(mOwner);
|
|
mOwner->ARIAAttributeDefaultWillChange(aElement, aAttribute, aModType);
|
|
}
|
|
|
|
void ARIAAttributeDefaultChanged(mozilla::dom::Element* aElement,
|
|
nsAtom* aAttribute,
|
|
int32_t aModType) override {
|
|
MOZ_ASSERT(mOwner);
|
|
mOwner->ARIAAttributeDefaultChanged(aElement, aAttribute, aModType);
|
|
}
|
|
|
|
MozExternalRefCountType AddRefWrapper() {
|
|
nsrefcnt count = ++mRefCnt;
|
|
NS_LOG_ADDREF(this, count, "MutationObserverWrapper", sizeof(*this));
|
|
return count;
|
|
}
|
|
|
|
MozExternalRefCountType ReleaseWrapper() {
|
|
--mRefCnt;
|
|
NS_LOG_RELEASE(this, mRefCnt, "MutationObserverWrapper");
|
|
if (mRefCnt == 0) {
|
|
mRefCnt = 1;
|
|
delete this;
|
|
return MozExternalRefCountType(0);
|
|
}
|
|
return mRefCnt;
|
|
}
|
|
|
|
private:
|
|
~MutationObserverWrapper() = default;
|
|
nsMultiMutationObserver* mOwner{nullptr};
|
|
};
|
|
|
|
NS_IMPL_QUERY_INTERFACE(MutationObserverWrapper, nsIMutationObserver);
|
|
|
|
MozExternalRefCountType MutationObserverWrapper::AddRef() {
|
|
MOZ_ASSERT(mOwner);
|
|
AddRefWrapper();
|
|
mOwner->AddRef();
|
|
return mRefCnt;
|
|
}
|
|
|
|
MozExternalRefCountType MutationObserverWrapper::Release() {
|
|
MOZ_ASSERT(mOwner);
|
|
mOwner->Release();
|
|
return ReleaseWrapper();
|
|
}
|
|
|
|
/******************************************************************************
|
|
* nsMultiMutationObserver
|
|
*****************************************************************************/
|
|
|
|
void nsMultiMutationObserver::AddMutationObserverToNode(nsINode* aNode) {
|
|
if (!aNode) {
|
|
return;
|
|
}
|
|
if (mWrapperForNode.Contains(aNode)) {
|
|
return;
|
|
}
|
|
auto* newWrapper = new MutationObserverWrapper{this};
|
|
newWrapper->AddRefWrapper();
|
|
mWrapperForNode.InsertOrUpdate(aNode, newWrapper);
|
|
aNode->AddMutationObserver(newWrapper);
|
|
}
|
|
|
|
void nsMultiMutationObserver::RemoveMutationObserverFromNode(nsINode* aNode) {
|
|
if (!aNode) {
|
|
return;
|
|
}
|
|
|
|
if (auto obs = mWrapperForNode.MaybeGet(aNode); obs.isSome()) {
|
|
aNode->RemoveMutationObserver(*obs);
|
|
mWrapperForNode.Remove(aNode);
|
|
(*obs)->ReleaseWrapper();
|
|
}
|
|
}
|
|
|
|
bool nsMultiMutationObserver::ContainsNode(const nsINode* aNode) const {
|
|
return mWrapperForNode.Contains(const_cast<nsINode*>(aNode));
|
|
}
|
|
|
|
/******************************************************************************
|
|
* nsStubMultiMutationObserver
|
|
*****************************************************************************/
|
|
|
|
NS_IMPL_NSIMUTATIONOBSERVER_CORE_STUB(nsStubMultiMutationObserver)
|
|
NS_IMPL_NSIMUTATIONOBSERVER_CONTENT(nsStubMultiMutationObserver)
|