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/. */
8 * nsStubMutationObserver is an implementation of the nsIMutationObserver
9 * interface (except for the methods on nsISupports) that is intended to be
10 * used as a base class within the content/layout library. All methods do
14 #include "nsStubMutationObserver.h"
15 #include "mozilla/RefCountType.h"
16 #include "nsISupports.h"
19 /******************************************************************************
20 * nsStubMutationObserver
21 *****************************************************************************/
23 NS_IMPL_NSIMUTATIONOBSERVER_CORE_STUB(nsStubMutationObserver
)
24 NS_IMPL_NSIMUTATIONOBSERVER_CONTENT(nsStubMutationObserver
)
26 /******************************************************************************
27 * MutationObserverWrapper
28 *****************************************************************************/
31 * @brief Wrapper class for a mutation observer that observes multiple nodes.
33 * This wrapper implements all methods of the nsIMutationObserver interface
34 * and forwards all calls to its owner, which is an instance of
35 * nsMultiMutationObserver.
37 * This class holds a reference to the owner and AddRefs/Releases its owner
38 * as well to ensure lifetime.
40 class MutationObserverWrapper final
: public nsIMutationObserver
{
44 explicit MutationObserverWrapper(nsMultiMutationObserver
* aOwner
)
47 void CharacterDataWillChange(nsIContent
* aContent
,
48 const CharacterDataChangeInfo
& aInfo
) override
{
50 mOwner
->CharacterDataWillChange(aContent
, aInfo
);
53 void CharacterDataChanged(nsIContent
* aContent
,
54 const CharacterDataChangeInfo
& aInfo
) override
{
56 mOwner
->CharacterDataChanged(aContent
, aInfo
);
59 void AttributeWillChange(mozilla::dom::Element
* aElement
,
60 int32_t aNameSpaceID
, nsAtom
* aAttribute
,
61 int32_t aModType
) override
{
63 mOwner
->AttributeWillChange(aElement
, aNameSpaceID
, aAttribute
, aModType
);
66 void AttributeChanged(mozilla::dom::Element
* aElement
, int32_t aNameSpaceID
,
67 nsAtom
* aAttribute
, int32_t aModType
,
68 const nsAttrValue
* aOldValue
) override
{
70 mOwner
->AttributeChanged(aElement
, aNameSpaceID
, aAttribute
, aModType
,
74 void AttributeSetToCurrentValue(mozilla::dom::Element
* aElement
,
76 nsAtom
* aAttribute
) override
{
78 mOwner
->AttributeSetToCurrentValue(aElement
, aNameSpaceID
, aAttribute
);
81 void ContentAppended(nsIContent
* aFirstNewContent
) override
{
83 mOwner
->ContentAppended(aFirstNewContent
);
86 void ContentInserted(nsIContent
* aChild
) override
{
88 mOwner
->ContentInserted(aChild
);
91 void ContentWillBeRemoved(nsIContent
* aChild
,
92 const BatchRemovalState
* aState
) override
{
94 mOwner
->ContentWillBeRemoved(aChild
, aState
);
97 void NodeWillBeDestroyed(nsINode
* aNode
) override
{
100 RefPtr
<nsMultiMutationObserver
> owner
= mOwner
;
101 owner
->NodeWillBeDestroyed(aNode
);
102 owner
->RemoveMutationObserverFromNode(aNode
);
107 void ParentChainChanged(nsIContent
* aContent
) override
{
109 mOwner
->ParentChainChanged(aContent
);
112 void ARIAAttributeDefaultWillChange(mozilla::dom::Element
* aElement
,
114 int32_t aModType
) override
{
116 mOwner
->ARIAAttributeDefaultWillChange(aElement
, aAttribute
, aModType
);
119 void ARIAAttributeDefaultChanged(mozilla::dom::Element
* aElement
,
121 int32_t aModType
) override
{
123 mOwner
->ARIAAttributeDefaultChanged(aElement
, aAttribute
, aModType
);
126 MozExternalRefCountType
AddRefWrapper() {
127 nsrefcnt count
= ++mRefCnt
;
128 NS_LOG_ADDREF(this, count
, "MutationObserverWrapper", sizeof(*this));
132 MozExternalRefCountType
ReleaseWrapper() {
134 NS_LOG_RELEASE(this, mRefCnt
, "MutationObserverWrapper");
138 return MozExternalRefCountType(0);
144 ~MutationObserverWrapper() = default;
145 nsMultiMutationObserver
* mOwner
{nullptr};
148 NS_IMPL_QUERY_INTERFACE(MutationObserverWrapper
, nsIMutationObserver
);
150 MozExternalRefCountType
MutationObserverWrapper::AddRef() {
157 MozExternalRefCountType
MutationObserverWrapper::Release() {
160 return ReleaseWrapper();
163 /******************************************************************************
164 * nsMultiMutationObserver
165 *****************************************************************************/
167 void nsMultiMutationObserver::AddMutationObserverToNode(nsINode
* aNode
) {
171 if (mWrapperForNode
.Contains(aNode
)) {
174 auto* newWrapper
= new MutationObserverWrapper
{this};
175 newWrapper
->AddRefWrapper();
176 mWrapperForNode
.InsertOrUpdate(aNode
, newWrapper
);
177 aNode
->AddMutationObserver(newWrapper
);
180 void nsMultiMutationObserver::RemoveMutationObserverFromNode(nsINode
* aNode
) {
185 if (auto obs
= mWrapperForNode
.MaybeGet(aNode
); obs
.isSome()) {
186 aNode
->RemoveMutationObserver(*obs
);
187 mWrapperForNode
.Remove(aNode
);
188 (*obs
)->ReleaseWrapper();
192 bool nsMultiMutationObserver::ContainsNode(const nsINode
* aNode
) const {
193 return mWrapperForNode
.Contains(const_cast<nsINode
*>(aNode
));
196 /******************************************************************************
197 * nsStubMultiMutationObserver
198 *****************************************************************************/
200 NS_IMPL_NSIMUTATIONOBSERVER_CORE_STUB(nsStubMultiMutationObserver
)
201 NS_IMPL_NSIMUTATIONOBSERVER_CONTENT(nsStubMultiMutationObserver
)