|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 #ifndef nsCategoryCache_h_ |
|
6 #define nsCategoryCache_h_ |
|
7 |
|
8 #include "mozilla/Attributes.h" |
|
9 |
|
10 #include "nsICategoryManager.h" |
|
11 #include "nsIObserver.h" |
|
12 #include "nsISimpleEnumerator.h" |
|
13 #include "nsISupportsPrimitives.h" |
|
14 |
|
15 #include "nsServiceManagerUtils.h" |
|
16 |
|
17 #include "nsAutoPtr.h" |
|
18 #include "nsCOMArray.h" |
|
19 #include "nsInterfaceHashtable.h" |
|
20 |
|
21 #include "nsXPCOM.h" |
|
22 |
|
23 class NS_COM_GLUE nsCategoryObserver MOZ_FINAL : public nsIObserver |
|
24 { |
|
25 public: |
|
26 nsCategoryObserver(const char* aCategory); |
|
27 ~nsCategoryObserver(); |
|
28 |
|
29 void ListenerDied(); |
|
30 nsInterfaceHashtable<nsCStringHashKey, nsISupports>& GetHash() |
|
31 { |
|
32 return mHash; |
|
33 } |
|
34 |
|
35 NS_DECL_ISUPPORTS |
|
36 NS_DECL_NSIOBSERVER |
|
37 private: |
|
38 void RemoveObservers(); |
|
39 |
|
40 nsInterfaceHashtable<nsCStringHashKey, nsISupports> mHash; |
|
41 nsCString mCategory; |
|
42 bool mObserversRemoved; |
|
43 }; |
|
44 |
|
45 /** |
|
46 * This is a helper class that caches services that are registered in a certain |
|
47 * category. The intended usage is that a service stores a variable of type |
|
48 * nsCategoryCache<nsIFoo> in a member variable, where nsIFoo is the interface |
|
49 * that these services should implement. The constructor of this class should |
|
50 * then get the name of the category. |
|
51 */ |
|
52 template<class T> |
|
53 class nsCategoryCache MOZ_FINAL |
|
54 { |
|
55 public: |
|
56 explicit nsCategoryCache(const char* aCategory) |
|
57 : mCategoryName(aCategory) |
|
58 { |
|
59 } |
|
60 ~nsCategoryCache() { |
|
61 if (mObserver) |
|
62 mObserver->ListenerDied(); |
|
63 } |
|
64 |
|
65 void GetEntries(nsCOMArray<T>& result) { |
|
66 // Lazy initialization, so that services in this category can't |
|
67 // cause reentrant getService (bug 386376) |
|
68 if (!mObserver) |
|
69 mObserver = new nsCategoryObserver(mCategoryName.get()); |
|
70 |
|
71 mObserver->GetHash().EnumerateRead(EntriesToArray, &result); |
|
72 } |
|
73 |
|
74 private: |
|
75 // Not to be implemented |
|
76 nsCategoryCache(const nsCategoryCache<T>&); |
|
77 |
|
78 static PLDHashOperator EntriesToArray(const nsACString& key, |
|
79 nsISupports* entry, void* arg) |
|
80 { |
|
81 nsCOMArray<T>& entries = *static_cast<nsCOMArray<T>*>(arg); |
|
82 |
|
83 nsCOMPtr<T> service = do_QueryInterface(entry); |
|
84 if (service) { |
|
85 entries.AppendObject(service); |
|
86 } |
|
87 return PL_DHASH_NEXT; |
|
88 } |
|
89 |
|
90 nsCString mCategoryName; |
|
91 nsRefPtr<nsCategoryObserver> mObserver; |
|
92 |
|
93 }; |
|
94 |
|
95 #endif |