|
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
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 #include "nsObserverList.h" |
|
7 |
|
8 #include "nsAutoPtr.h" |
|
9 #include "nsCOMArray.h" |
|
10 #include "nsISimpleEnumerator.h" |
|
11 #include "xpcpublic.h" |
|
12 |
|
13 nsresult |
|
14 nsObserverList::AddObserver(nsIObserver* anObserver, bool ownsWeak) |
|
15 { |
|
16 NS_ASSERTION(anObserver, "Null input"); |
|
17 |
|
18 if (!ownsWeak) { |
|
19 ObserverRef* o = mObservers.AppendElement(anObserver); |
|
20 if (!o) |
|
21 return NS_ERROR_OUT_OF_MEMORY; |
|
22 |
|
23 return NS_OK; |
|
24 } |
|
25 |
|
26 nsCOMPtr<nsIWeakReference> weak = do_GetWeakReference(anObserver); |
|
27 if (!weak) |
|
28 return NS_NOINTERFACE; |
|
29 |
|
30 ObserverRef *o = mObservers.AppendElement(weak); |
|
31 if (!o) |
|
32 return NS_ERROR_OUT_OF_MEMORY; |
|
33 |
|
34 return NS_OK; |
|
35 } |
|
36 |
|
37 nsresult |
|
38 nsObserverList::RemoveObserver(nsIObserver* anObserver) |
|
39 { |
|
40 NS_ASSERTION(anObserver, "Null input"); |
|
41 |
|
42 if (mObservers.RemoveElement(static_cast<nsISupports*>(anObserver))) |
|
43 return NS_OK; |
|
44 |
|
45 nsCOMPtr<nsIWeakReference> observerRef = do_GetWeakReference(anObserver); |
|
46 if (!observerRef) |
|
47 return NS_ERROR_FAILURE; |
|
48 |
|
49 if (!mObservers.RemoveElement(observerRef)) |
|
50 return NS_ERROR_FAILURE; |
|
51 |
|
52 return NS_OK; |
|
53 } |
|
54 |
|
55 nsresult |
|
56 nsObserverList::GetObserverList(nsISimpleEnumerator** anEnumerator) |
|
57 { |
|
58 nsRefPtr<nsObserverEnumerator> e(new nsObserverEnumerator(this)); |
|
59 e.forget(anEnumerator); |
|
60 return NS_OK; |
|
61 } |
|
62 |
|
63 void |
|
64 nsObserverList::FillObserverArray(nsCOMArray<nsIObserver> &aArray) |
|
65 { |
|
66 aArray.SetCapacity(mObservers.Length()); |
|
67 |
|
68 nsTArray<ObserverRef> observers(mObservers); |
|
69 |
|
70 for (int32_t i = observers.Length() - 1; i >= 0; --i) { |
|
71 if (observers[i].isWeakRef) { |
|
72 nsCOMPtr<nsIObserver> o(do_QueryReferent(observers[i].asWeak())); |
|
73 if (o) { |
|
74 aArray.AppendObject(o); |
|
75 } |
|
76 else { |
|
77 // the object has gone away, remove the weakref |
|
78 mObservers.RemoveElement(observers[i].asWeak()); |
|
79 } |
|
80 } |
|
81 else { |
|
82 aArray.AppendObject(observers[i].asObserver()); |
|
83 } |
|
84 } |
|
85 } |
|
86 |
|
87 void |
|
88 nsObserverList::NotifyObservers(nsISupports *aSubject, |
|
89 const char *aTopic, |
|
90 const char16_t *someData) |
|
91 { |
|
92 nsCOMArray<nsIObserver> observers; |
|
93 FillObserverArray(observers); |
|
94 |
|
95 for (int32_t i = 0; i < observers.Count(); ++i) { |
|
96 observers[i]->Observe(aSubject, aTopic, someData); |
|
97 } |
|
98 } |
|
99 |
|
100 void |
|
101 nsObserverList::UnmarkGrayStrongObservers() |
|
102 { |
|
103 for (uint32_t i = 0; i < mObservers.Length(); ++i) { |
|
104 if (!mObservers[i].isWeakRef) { |
|
105 xpc_TryUnmarkWrappedGrayObject(mObservers[i].asObserver()); |
|
106 } |
|
107 } |
|
108 } |
|
109 |
|
110 NS_IMPL_ISUPPORTS(nsObserverEnumerator, nsISimpleEnumerator) |
|
111 |
|
112 nsObserverEnumerator::nsObserverEnumerator(nsObserverList* aObserverList) |
|
113 : mIndex(0) |
|
114 { |
|
115 aObserverList->FillObserverArray(mObservers); |
|
116 } |
|
117 |
|
118 NS_IMETHODIMP |
|
119 nsObserverEnumerator::HasMoreElements(bool *aResult) |
|
120 { |
|
121 *aResult = (mIndex < mObservers.Count()); |
|
122 return NS_OK; |
|
123 } |
|
124 |
|
125 NS_IMETHODIMP |
|
126 nsObserverEnumerator::GetNext(nsISupports* *aResult) |
|
127 { |
|
128 if (mIndex == mObservers.Count()) { |
|
129 NS_ERROR("Enumerating after HasMoreElements returned false."); |
|
130 return NS_ERROR_UNEXPECTED; |
|
131 } |
|
132 |
|
133 NS_ADDREF(*aResult = mObservers[mIndex]); |
|
134 ++mIndex; |
|
135 return NS_OK; |
|
136 } |