Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/base/nsIdentifierMapEntry.h
Line
Count
Source (jump to first uncovered line)
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/. */
6
7
/*
8
 * Base class for all our document implementations.
9
 */
10
11
#ifndef nsIdentifierMapEntry_h
12
#define nsIdentifierMapEntry_h
13
14
#include "PLDHashTable.h"
15
16
#include "mozilla/MemoryReporting.h"
17
#include "mozilla/Move.h"
18
#include "mozilla/net/ReferrerPolicy.h"
19
20
#include "nsCOMPtr.h"
21
#include "nsAtom.h"
22
#include "nsHashKeys.h"
23
#include "nsTArray.h"
24
#include "nsTHashtable.h"
25
26
class nsIContent;
27
class nsContentList;
28
class nsBaseContentList;
29
30
namespace mozilla {
31
namespace dom {
32
class Element;
33
}
34
}
35
36
/**
37
 * Right now our identifier map entries contain information for 'name'
38
 * and 'id' mappings of a given string. This is so that
39
 * nsHTMLDocument::ResolveName only has to do one hash lookup instead
40
 * of two. It's not clear whether this still matters for performance.
41
 *
42
 * We also store the document.all result list here. This is mainly so that
43
 * when all elements with the given ID are removed and we remove
44
 * the ID's nsIdentifierMapEntry, the document.all result is released too.
45
 * Perhaps the document.all results should have their own hashtable
46
 * in nsHTMLDocument.
47
 */
48
class nsIdentifierMapEntry : public PLDHashEntryHdr
49
{
50
  typedef mozilla::dom::Element Element;
51
  typedef mozilla::net::ReferrerPolicy ReferrerPolicy;
52
53
  /**
54
   * @see nsIDocument::IDTargetObserver, this is just here to avoid include
55
   * hell.
56
   */
57
  typedef bool (* IDTargetObserver)(Element* aOldElement,
58
                                    Element* aNewelement, void* aData);
59
public:
60
  struct AtomOrString
61
  {
62
0
    MOZ_IMPLICIT AtomOrString(nsAtom* aAtom) : mAtom(aAtom) {}
63
0
    MOZ_IMPLICIT AtomOrString(const nsAString& aString) : mString(aString) {}
64
    AtomOrString(const AtomOrString& aOther)
65
      : mAtom(aOther.mAtom)
66
      , mString(aOther.mString)
67
0
    {
68
0
    }
69
70
    AtomOrString(AtomOrString&& aOther)
71
      : mAtom(aOther.mAtom.forget())
72
      , mString(aOther.mString)
73
0
    {
74
0
    }
75
76
    RefPtr<nsAtom> mAtom;
77
    const nsString mString;
78
  };
79
80
  typedef const AtomOrString& KeyType;
81
  typedef const AtomOrString* KeyTypePointer;
82
83
  explicit nsIdentifierMapEntry(const AtomOrString& aKey);
84
  explicit nsIdentifierMapEntry(const AtomOrString* aKey);
85
  nsIdentifierMapEntry(nsIdentifierMapEntry&& aOther);
86
  ~nsIdentifierMapEntry();
87
88
  nsString GetKeyAsString() const
89
0
  {
90
0
    if (mKey.mAtom) {
91
0
      return nsAtomString(mKey.mAtom);
92
0
    }
93
0
94
0
    return mKey.mString;
95
0
  }
96
97
  bool KeyEquals(const KeyTypePointer aOtherKey) const
98
0
  {
99
0
    if (mKey.mAtom) {
100
0
      if (aOtherKey->mAtom) {
101
0
        return mKey.mAtom == aOtherKey->mAtom;
102
0
      }
103
0
104
0
      return mKey.mAtom->Equals(aOtherKey->mString);
105
0
    }
106
0
107
0
    if (aOtherKey->mAtom) {
108
0
      return aOtherKey->mAtom->Equals(mKey.mString);
109
0
    }
110
0
111
0
    return mKey.mString.Equals(aOtherKey->mString);
112
0
  }
113
114
0
  static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
115
116
  static PLDHashNumber HashKey(const KeyTypePointer aKey)
117
0
  {
118
0
    return aKey->mAtom ?
119
0
      aKey->mAtom->hash() : mozilla::HashString(aKey->mString);
120
0
  }
121
122
  enum { ALLOW_MEMMOVE = false };
123
124
  void AddNameElement(nsINode* aDocument, Element* aElement);
125
  void RemoveNameElement(Element* aElement);
126
  bool IsEmpty();
127
0
  nsBaseContentList* GetNameContentList() {
128
0
    return mNameContentList;
129
0
  }
130
  bool HasNameElement() const;
131
132
  /**
133
   * Returns the element if we know the element associated with this
134
   * id. Otherwise returns null.
135
   */
136
  Element* GetIdElement();
137
  /**
138
   * Returns the list of all elements associated with this id.
139
   */
140
0
  const nsTArray<Element*>& GetIdElements() const {
141
0
    return mIdContentList;
142
0
  }
143
  /**
144
   * If this entry has a non-null image element set (using SetImageElement),
145
   * the image element will be returned, otherwise the same as GetIdElement().
146
   */
147
  Element* GetImageIdElement();
148
  /**
149
   * This can fire ID change callbacks.
150
   * @return true if the content could be added, false if we failed due
151
   * to OOM.
152
   */
153
  bool AddIdElement(Element* aElement);
154
  /**
155
   * This can fire ID change callbacks.
156
   */
157
  void RemoveIdElement(Element* aElement);
158
  /**
159
   * Set the image element override for this ID. This will be returned by
160
   * GetIdElement(true) if non-null.
161
   */
162
  void SetImageElement(Element* aElement);
163
  bool HasIdElementExposedAsHTMLDocumentProperty();
164
165
  bool HasContentChangeCallback() { return mChangeCallbacks != nullptr; }
166
  void AddContentChangeCallback(IDTargetObserver aCallback,
167
                                void* aData, bool aForImage);
168
  void RemoveContentChangeCallback(IDTargetObserver aCallback,
169
                                void* aData, bool aForImage);
170
171
  void Traverse(nsCycleCollectionTraversalCallback* aCallback);
172
173
  struct ChangeCallback {
174
    IDTargetObserver mCallback;
175
    void* mData;
176
    bool mForImage;
177
  };
178
179
  struct ChangeCallbackEntry : public PLDHashEntryHdr {
180
    typedef const ChangeCallback KeyType;
181
    typedef const ChangeCallback* KeyTypePointer;
182
183
    explicit ChangeCallbackEntry(const ChangeCallback* aKey) :
184
0
      mKey(*aKey) { }
185
    ChangeCallbackEntry(ChangeCallbackEntry&& aOther) :
186
      PLDHashEntryHdr(std::move(aOther)),
187
      mKey(std::move(aOther.mKey)) { }
188
189
    KeyType GetKey() const { return mKey; }
190
0
    bool KeyEquals(KeyTypePointer aKey) const {
191
0
      return aKey->mCallback == mKey.mCallback &&
192
0
             aKey->mData == mKey.mData &&
193
0
             aKey->mForImage == mKey.mForImage;
194
0
    }
195
196
0
    static KeyTypePointer KeyToPointer(KeyType& aKey) { return &aKey; }
197
    static PLDHashNumber HashKey(KeyTypePointer aKey)
198
0
    {
199
0
      return mozilla::HashGeneric(aKey->mCallback, aKey->mData);
200
0
    }
201
    enum { ALLOW_MEMMOVE = true };
202
203
    ChangeCallback mKey;
204
  };
205
206
  size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
207
208
private:
209
  nsIdentifierMapEntry(const nsIdentifierMapEntry& aOther) = delete;
210
  nsIdentifierMapEntry& operator=(const nsIdentifierMapEntry& aOther) = delete;
211
212
  void FireChangeCallbacks(Element* aOldElement, Element* aNewElement,
213
                           bool aImageOnly = false);
214
215
  AtomOrString mKey;
216
  // empty if there are no elements with this ID.
217
  // The elements are stored as weak pointers.
218
  AutoTArray<Element*, 1> mIdContentList;
219
  RefPtr<nsBaseContentList> mNameContentList;
220
  nsAutoPtr<nsTHashtable<ChangeCallbackEntry> > mChangeCallbacks;
221
  RefPtr<Element> mImageElement;
222
};
223
224
#endif // #ifndef nsIdentifierMapEntry_h