/src/mozilla-central/xpcom/ds/nsHashPropertyBag.cpp
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 | | #include "nsHashPropertyBag.h" |
8 | | #include "nsArray.h" |
9 | | #include "nsArrayEnumerator.h" |
10 | | #include "nsIVariant.h" |
11 | | #include "nsIProperty.h" |
12 | | #include "nsThreadUtils.h" |
13 | | #include "nsVariant.h" |
14 | | #include "mozilla/Attributes.h" |
15 | | #include "mozilla/Move.h" |
16 | | |
17 | | /* |
18 | | * nsHashPropertyBagBase implementation. |
19 | | */ |
20 | | |
21 | | NS_IMETHODIMP |
22 | | nsHashPropertyBagBase::HasKey(const nsAString& aName, bool* aResult) |
23 | 0 | { |
24 | 0 | *aResult = mPropertyHash.Get(aName, nullptr); |
25 | 0 | return NS_OK; |
26 | 0 | } |
27 | | |
28 | | NS_IMETHODIMP |
29 | | nsHashPropertyBagBase::Get(const nsAString& aName, nsIVariant** aResult) |
30 | 0 | { |
31 | 0 | if (!mPropertyHash.Get(aName, aResult)) { |
32 | 0 | *aResult = nullptr; |
33 | 0 | } |
34 | 0 |
|
35 | 0 | return NS_OK; |
36 | 0 | } |
37 | | |
38 | | NS_IMETHODIMP |
39 | | nsHashPropertyBagBase::GetProperty(const nsAString& aName, nsIVariant** aResult) |
40 | 0 | { |
41 | 0 | bool isFound = mPropertyHash.Get(aName, aResult); |
42 | 0 | if (!isFound) { |
43 | 0 | return NS_ERROR_FAILURE; |
44 | 0 | } |
45 | 0 | |
46 | 0 | return NS_OK; |
47 | 0 | } |
48 | | |
49 | | NS_IMETHODIMP |
50 | | nsHashPropertyBagBase::SetProperty(const nsAString& aName, nsIVariant* aValue) |
51 | 0 | { |
52 | 0 | if (NS_WARN_IF(!aValue)) { |
53 | 0 | return NS_ERROR_INVALID_ARG; |
54 | 0 | } |
55 | 0 | |
56 | 0 | mPropertyHash.Put(aName, aValue); |
57 | 0 |
|
58 | 0 | return NS_OK; |
59 | 0 | } |
60 | | |
61 | | NS_IMETHODIMP |
62 | | nsHashPropertyBagBase::DeleteProperty(const nsAString& aName) |
63 | 0 | { |
64 | 0 | return mPropertyHash.Remove(aName) ? NS_OK : NS_ERROR_FAILURE; |
65 | 0 | } |
66 | | |
67 | | |
68 | | // |
69 | | // nsSimpleProperty class and impl; used for GetEnumerator |
70 | | // |
71 | | |
72 | | class nsSimpleProperty final : public nsIProperty |
73 | | { |
74 | 0 | ~nsSimpleProperty() {} |
75 | | |
76 | | public: |
77 | | nsSimpleProperty(const nsAString& aName, nsIVariant* aValue) |
78 | | : mName(aName) |
79 | | , mValue(aValue) |
80 | 0 | { |
81 | 0 | } |
82 | | |
83 | | NS_DECL_ISUPPORTS |
84 | | NS_DECL_NSIPROPERTY |
85 | | protected: |
86 | | nsString mName; |
87 | | nsCOMPtr<nsIVariant> mValue; |
88 | | }; |
89 | | |
90 | | NS_IMPL_ISUPPORTS(nsSimpleProperty, nsIProperty) |
91 | | |
92 | | NS_IMETHODIMP |
93 | | nsSimpleProperty::GetName(nsAString& aName) |
94 | 0 | { |
95 | 0 | aName.Assign(mName); |
96 | 0 | return NS_OK; |
97 | 0 | } |
98 | | |
99 | | NS_IMETHODIMP |
100 | | nsSimpleProperty::GetValue(nsIVariant** aValue) |
101 | 0 | { |
102 | 0 | NS_IF_ADDREF(*aValue = mValue); |
103 | 0 | return NS_OK; |
104 | 0 | } |
105 | | |
106 | | // end nsSimpleProperty |
107 | | |
108 | | NS_IMETHODIMP |
109 | | nsHashPropertyBagBase::GetEnumerator(nsISimpleEnumerator** aResult) |
110 | 0 | { |
111 | 0 | nsCOMPtr<nsIMutableArray> propertyArray = nsArray::Create(); |
112 | 0 | if (!propertyArray) { |
113 | 0 | return NS_ERROR_OUT_OF_MEMORY; |
114 | 0 | } |
115 | 0 | |
116 | 0 | for (auto iter = mPropertyHash.Iter(); !iter.Done(); iter.Next()) { |
117 | 0 | const nsAString& key = iter.Key(); |
118 | 0 | nsIVariant* data = iter.UserData(); |
119 | 0 | nsSimpleProperty* sprop = new nsSimpleProperty(key, data); |
120 | 0 | propertyArray->AppendElement(sprop); |
121 | 0 | } |
122 | 0 |
|
123 | 0 | return NS_NewArrayEnumerator(aResult, propertyArray, |
124 | 0 | NS_GET_IID(nsIProperty)); |
125 | 0 | } |
126 | | |
127 | | #define IMPL_GETSETPROPERTY_AS(Name, Type) \ |
128 | | NS_IMETHODIMP \ |
129 | 0 | nsHashPropertyBagBase::GetPropertyAs ## Name (const nsAString & prop, Type *_retval) \ |
130 | 0 | { \ |
131 | 0 | nsIVariant* v = mPropertyHash.GetWeak(prop); \ |
132 | 0 | if (!v) \ |
133 | 0 | return NS_ERROR_NOT_AVAILABLE; \ |
134 | 0 | return v->GetAs ## Name(_retval); \ |
135 | 0 | } \ Unexecuted instantiation: nsHashPropertyBagBase::GetPropertyAsInt32(nsTSubstring<char16_t> const&, int*) Unexecuted instantiation: nsHashPropertyBagBase::GetPropertyAsUint32(nsTSubstring<char16_t> const&, unsigned int*) Unexecuted instantiation: nsHashPropertyBagBase::GetPropertyAsInt64(nsTSubstring<char16_t> const&, long*) Unexecuted instantiation: nsHashPropertyBagBase::GetPropertyAsUint64(nsTSubstring<char16_t> const&, unsigned long*) Unexecuted instantiation: nsHashPropertyBagBase::GetPropertyAsDouble(nsTSubstring<char16_t> const&, double*) Unexecuted instantiation: nsHashPropertyBagBase::GetPropertyAsBool(nsTSubstring<char16_t> const&, bool*) |
136 | | \ |
137 | | NS_IMETHODIMP \ |
138 | 0 | nsHashPropertyBagBase::SetPropertyAs ## Name (const nsAString & prop, Type value) \ |
139 | 0 | { \ |
140 | 0 | nsCOMPtr<nsIWritableVariant> var = new nsVariant(); \ |
141 | 0 | var->SetAs ## Name(value); \ |
142 | 0 | return SetProperty(prop, var); \ |
143 | 0 | } Unexecuted instantiation: nsHashPropertyBagBase::SetPropertyAsInt32(nsTSubstring<char16_t> const&, int) Unexecuted instantiation: nsHashPropertyBagBase::SetPropertyAsUint32(nsTSubstring<char16_t> const&, unsigned int) Unexecuted instantiation: nsHashPropertyBagBase::SetPropertyAsInt64(nsTSubstring<char16_t> const&, long) Unexecuted instantiation: nsHashPropertyBagBase::SetPropertyAsUint64(nsTSubstring<char16_t> const&, unsigned long) Unexecuted instantiation: nsHashPropertyBagBase::SetPropertyAsDouble(nsTSubstring<char16_t> const&, double) Unexecuted instantiation: nsHashPropertyBagBase::SetPropertyAsBool(nsTSubstring<char16_t> const&, bool) |
144 | | |
145 | | IMPL_GETSETPROPERTY_AS(Int32, int32_t) |
146 | | IMPL_GETSETPROPERTY_AS(Uint32, uint32_t) |
147 | | IMPL_GETSETPROPERTY_AS(Int64, int64_t) |
148 | | IMPL_GETSETPROPERTY_AS(Uint64, uint64_t) |
149 | | IMPL_GETSETPROPERTY_AS(Double, double) |
150 | | IMPL_GETSETPROPERTY_AS(Bool, bool) |
151 | | |
152 | | |
153 | | NS_IMETHODIMP |
154 | | nsHashPropertyBagBase::GetPropertyAsAString(const nsAString& aProp, |
155 | | nsAString& aResult) |
156 | 0 | { |
157 | 0 | nsIVariant* v = mPropertyHash.GetWeak(aProp); |
158 | 0 | if (!v) { |
159 | 0 | return NS_ERROR_NOT_AVAILABLE; |
160 | 0 | } |
161 | 0 | return v->GetAsAString(aResult); |
162 | 0 | } |
163 | | |
164 | | NS_IMETHODIMP |
165 | | nsHashPropertyBagBase::GetPropertyAsACString(const nsAString& aProp, |
166 | | nsACString& aResult) |
167 | 0 | { |
168 | 0 | nsIVariant* v = mPropertyHash.GetWeak(aProp); |
169 | 0 | if (!v) { |
170 | 0 | return NS_ERROR_NOT_AVAILABLE; |
171 | 0 | } |
172 | 0 | return v->GetAsACString(aResult); |
173 | 0 | } |
174 | | |
175 | | NS_IMETHODIMP |
176 | | nsHashPropertyBagBase::GetPropertyAsAUTF8String(const nsAString& aProp, |
177 | | nsACString& aResult) |
178 | 0 | { |
179 | 0 | nsIVariant* v = mPropertyHash.GetWeak(aProp); |
180 | 0 | if (!v) { |
181 | 0 | return NS_ERROR_NOT_AVAILABLE; |
182 | 0 | } |
183 | 0 | return v->GetAsAUTF8String(aResult); |
184 | 0 | } |
185 | | |
186 | | NS_IMETHODIMP |
187 | | nsHashPropertyBagBase::GetPropertyAsInterface(const nsAString& aProp, |
188 | | const nsIID& aIID, |
189 | | void** aResult) |
190 | 0 | { |
191 | 0 | nsIVariant* v = mPropertyHash.GetWeak(aProp); |
192 | 0 | if (!v) { |
193 | 0 | return NS_ERROR_NOT_AVAILABLE; |
194 | 0 | } |
195 | 0 | nsCOMPtr<nsISupports> val; |
196 | 0 | nsresult rv = v->GetAsISupports(getter_AddRefs(val)); |
197 | 0 | if (NS_FAILED(rv)) { |
198 | 0 | return rv; |
199 | 0 | } |
200 | 0 | if (!val) { |
201 | 0 | // We have a value, but it's null |
202 | 0 | *aResult = nullptr; |
203 | 0 | return NS_OK; |
204 | 0 | } |
205 | 0 | return val->QueryInterface(aIID, aResult); |
206 | 0 | } |
207 | | |
208 | | NS_IMETHODIMP |
209 | | nsHashPropertyBagBase::SetPropertyAsAString(const nsAString& aProp, |
210 | | const nsAString& aValue) |
211 | 0 | { |
212 | 0 | nsCOMPtr<nsIWritableVariant> var = new nsVariant(); |
213 | 0 | var->SetAsAString(aValue); |
214 | 0 | return SetProperty(aProp, var); |
215 | 0 | } |
216 | | |
217 | | NS_IMETHODIMP |
218 | | nsHashPropertyBagBase::SetPropertyAsACString(const nsAString& aProp, |
219 | | const nsACString& aValue) |
220 | 0 | { |
221 | 0 | nsCOMPtr<nsIWritableVariant> var = new nsVariant(); |
222 | 0 | var->SetAsACString(aValue); |
223 | 0 | return SetProperty(aProp, var); |
224 | 0 | } |
225 | | |
226 | | NS_IMETHODIMP |
227 | | nsHashPropertyBagBase::SetPropertyAsAUTF8String(const nsAString& aProp, |
228 | | const nsACString& aValue) |
229 | 0 | { |
230 | 0 | nsCOMPtr<nsIWritableVariant> var = new nsVariant(); |
231 | 0 | var->SetAsAUTF8String(aValue); |
232 | 0 | return SetProperty(aProp, var); |
233 | 0 | } |
234 | | |
235 | | NS_IMETHODIMP |
236 | | nsHashPropertyBagBase::SetPropertyAsInterface(const nsAString& aProp, |
237 | | nsISupports* aValue) |
238 | 0 | { |
239 | 0 | nsCOMPtr<nsIWritableVariant> var = new nsVariant(); |
240 | 0 | var->SetAsISupports(aValue); |
241 | 0 | return SetProperty(aProp, var); |
242 | 0 | } |
243 | | |
244 | | |
245 | | /* |
246 | | * nsHashPropertyBag implementation. |
247 | | */ |
248 | | |
249 | | NS_IMPL_ADDREF(nsHashPropertyBag) |
250 | | NS_IMPL_RELEASE(nsHashPropertyBag) |
251 | | |
252 | 0 | NS_INTERFACE_MAP_BEGIN(nsHashPropertyBag) |
253 | 0 | NS_INTERFACE_MAP_ENTRY(nsIWritablePropertyBag) |
254 | 0 | NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIPropertyBag, nsIWritablePropertyBag) |
255 | 0 | NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWritablePropertyBag) |
256 | 0 | NS_INTERFACE_MAP_ENTRY(nsIPropertyBag2) |
257 | 0 | NS_INTERFACE_MAP_ENTRY(nsIWritablePropertyBag2) |
258 | 0 | NS_INTERFACE_MAP_END |
259 | | |
260 | | /* |
261 | | * We need to ensure that the hashtable is destroyed on the main thread, as |
262 | | * the nsIVariant values are main-thread only objects. |
263 | | */ |
264 | | class ProxyHashtableDestructor final : public mozilla::Runnable |
265 | | { |
266 | | public: |
267 | | using HashtableType = nsInterfaceHashtable<nsStringHashKey, nsIVariant>; |
268 | | explicit ProxyHashtableDestructor(HashtableType&& aTable) |
269 | | : mozilla::Runnable("ProxyHashtableDestructor") |
270 | | , mPropertyHash(std::move(aTable)) |
271 | 0 | {} |
272 | | |
273 | | NS_IMETHODIMP |
274 | | Run() override |
275 | 0 | { |
276 | 0 | MOZ_ASSERT(NS_IsMainThread()); |
277 | 0 | HashtableType table(std::move(mPropertyHash)); |
278 | 0 | return NS_OK; |
279 | 0 | } |
280 | | |
281 | | private: |
282 | | HashtableType mPropertyHash; |
283 | | }; |
284 | | |
285 | | nsHashPropertyBag::~nsHashPropertyBag() |
286 | 5 | { |
287 | 5 | if (!NS_IsMainThread()) { |
288 | 0 | RefPtr<ProxyHashtableDestructor> runnable = |
289 | 0 | new ProxyHashtableDestructor(std::move(mPropertyHash)); |
290 | 0 | MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable)); |
291 | 0 | } |
292 | 5 | } |
293 | | |
294 | | /* |
295 | | * nsHashPropertyBagCC implementation. |
296 | | */ |
297 | | |
298 | | NS_IMPL_CYCLE_COLLECTION(nsHashPropertyBagCC, mPropertyHash) |
299 | | |
300 | | NS_IMPL_CYCLE_COLLECTING_ADDREF(nsHashPropertyBagCC) |
301 | | NS_IMPL_CYCLE_COLLECTING_RELEASE(nsHashPropertyBagCC) |
302 | | |
303 | 0 | NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsHashPropertyBagCC) |
304 | 0 | NS_INTERFACE_MAP_ENTRY(nsIWritablePropertyBag) |
305 | 0 | NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIPropertyBag, nsIWritablePropertyBag) |
306 | 0 | NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWritablePropertyBag) |
307 | 0 | NS_INTERFACE_MAP_ENTRY(nsIPropertyBag2) |
308 | 0 | NS_INTERFACE_MAP_ENTRY(nsIWritablePropertyBag2) |
309 | 0 | NS_INTERFACE_MAP_END |