Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/ManualNAC.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* This Source Code Form is subject to the terms of the Mozilla Public
3
 * License, v. 2.0. If a copy of the MPL was not distributed with this
4
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6
#ifndef mozilla_ManualNAC_h
7
#define mozilla_ManualNAC_h
8
9
#include "mozilla/dom/Element.h"
10
#include "mozilla/RefPtr.h"
11
12
namespace mozilla {
13
14
// 16 seems to be the maximum number of manual Native Anonymous Content (NAC)
15
// nodes that editor creates for a given element.
16
//
17
// These need to be manually removed by the machinery that sets the NAC,
18
// otherwise we'll leak.
19
typedef AutoTArray<RefPtr<dom::Element>, 16> ManualNACArray;
20
21
/**
22
 * Smart pointer class to own "manual" Native Anonymous Content, and perform
23
 * the necessary registration and deregistration on the parent element.
24
 */
25
class ManualNACPtr final
26
{
27
public:
28
0
  ManualNACPtr() {}
29
0
  MOZ_IMPLICIT ManualNACPtr(decltype(nullptr)) {}
30
  explicit ManualNACPtr(already_AddRefed<Element> aNewNAC)
31
    : mPtr(aNewNAC)
32
0
  {
33
0
    if (!mPtr) {
34
0
      return;
35
0
    }
36
0
37
0
    // Record the NAC on the element, so that AllChildrenIterator can find it.
38
0
    nsIContent* parentContent = mPtr->GetParent();
39
0
    auto nac = static_cast<ManualNACArray*>(
40
0
        parentContent->GetProperty(nsGkAtoms::manualNACProperty));
41
0
    if (!nac) {
42
0
      nac = new ManualNACArray();
43
0
      parentContent->SetProperty(nsGkAtoms::manualNACProperty, nac,
44
0
                                 nsINode::DeleteProperty<ManualNACArray>);
45
0
    }
46
0
    nac->AppendElement(mPtr);
47
0
  }
48
49
  // We use move semantics, and delete the copy-constructor and operator=.
50
0
  ManualNACPtr(ManualNACPtr&& aOther) : mPtr(aOther.mPtr.forget()) {}
51
  ManualNACPtr(ManualNACPtr& aOther) = delete;
52
  ManualNACPtr& operator=(ManualNACPtr&& aOther)
53
0
  {
54
0
    mPtr = aOther.mPtr.forget();
55
0
    return *this;
56
0
  }
57
  ManualNACPtr& operator=(ManualNACPtr& aOther) = delete;
58
59
0
  ~ManualNACPtr() { Reset(); }
60
61
  void Reset()
62
0
  {
63
0
    if (!mPtr) {
64
0
      return;
65
0
    }
66
0
67
0
    RefPtr<Element> ptr = mPtr.forget();
68
0
    nsIContent* parentContent = ptr->GetParent();
69
0
    if (!parentContent) {
70
0
      NS_WARNING("Potentially leaking manual NAC");
71
0
      return;
72
0
    }
73
0
74
0
    // Remove reference from the parent element.
75
0
    auto nac = static_cast<mozilla::ManualNACArray*>(
76
0
        parentContent->GetProperty(nsGkAtoms::manualNACProperty));
77
0
    // nsIDocument::AdoptNode might remove all properties before destroying
78
0
    // editor.  So we have to consider that NAC could be already removed.
79
0
    if (nac) {
80
0
      nac->RemoveElement(ptr);
81
0
      if (nac->IsEmpty()) {
82
0
        parentContent->DeleteProperty(nsGkAtoms::manualNACProperty);
83
0
      }
84
0
    }
85
0
86
0
    ptr->UnbindFromTree();
87
0
  }
88
89
0
  Element* get() const { return mPtr.get(); }
90
0
  Element* operator->() const { return get(); }
91
  operator Element*() const &
92
0
  {
93
0
    return get();
94
0
  }
95
96
private:
97
  RefPtr<Element> mPtr;
98
};
99
100
} // namespace mozilla
101
102
inline void
103
ImplCycleCollectionUnlink(mozilla::ManualNACPtr& field)
104
0
{
105
0
  field.Reset();
106
0
}
107
108
inline void
109
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& callback,
110
                            const mozilla::ManualNACPtr& field,
111
                            const char* name,
112
                            uint32_t flags = 0)
113
0
{
114
0
  CycleCollectionNoteChild(callback, field.get(), name, flags);
115
0
}
116
117
#endif // #ifndef mozilla_ManualNAC_h