/src/mozilla-central/toolkit/system/gnome/nsGConfService.cpp
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 | | #include "mozilla/ArrayUtils.h" |
7 | | #include "nsGConfService.h" |
8 | | #include "nsString.h" |
9 | | #include "nsCOMPtr.h" |
10 | | #include "nsComponentManagerUtils.h" |
11 | | #include "nsISupportsPrimitives.h" |
12 | | #include "nsIMutableArray.h" |
13 | | #include "nsXULAppAPI.h" |
14 | | #include "prlink.h" |
15 | | |
16 | | #include <gconf/gconf-client.h> |
17 | | |
18 | | using namespace mozilla; |
19 | | |
20 | | #define GCONF_FUNCTIONS \ |
21 | 0 | FUNC(gconf_client_get_default, GConfClient*, (void)) \ |
22 | 0 | FUNC(gconf_client_get_bool, gboolean, (GConfClient*, const gchar*, GError**)) \ |
23 | 0 | FUNC(gconf_client_get_string, gchar*, (GConfClient*, const gchar*, GError**)) \ |
24 | 0 | FUNC(gconf_client_get_int, gint, (GConfClient*, const gchar*, GError**)) \ |
25 | 0 | FUNC(gconf_client_get_float, gdouble, (GConfClient*, const gchar*, GError**)) \ |
26 | 0 | FUNC(gconf_client_get_list, GSList*, (GConfClient*, const gchar*, GConfValueType, GError**)) \ |
27 | 0 | FUNC(gconf_client_set_bool, gboolean, (GConfClient*, const gchar*, gboolean, GError**)) \ |
28 | 0 | FUNC(gconf_client_set_string, gboolean, (GConfClient*, const gchar*, const gchar*, GError**)) \ |
29 | 0 | FUNC(gconf_client_set_int, gboolean, (GConfClient*, const gchar*, gint, GError**)) \ |
30 | 0 | FUNC(gconf_client_set_float, gboolean, (GConfClient*, const gchar*, gdouble, GError**)) \ |
31 | 0 | FUNC(gconf_client_unset, gboolean, (GConfClient*, const gchar*, GError**)) |
32 | | |
33 | | #define FUNC(name, type, params) \ |
34 | | typedef type (*_##name##_fn) params; \ |
35 | | static _##name##_fn _##name; |
36 | | |
37 | | GCONF_FUNCTIONS |
38 | | |
39 | | #undef FUNC |
40 | | |
41 | 0 | #define gconf_client_get_default _gconf_client_get_default |
42 | 0 | #define gconf_client_get_bool _gconf_client_get_bool |
43 | 0 | #define gconf_client_get_string _gconf_client_get_string |
44 | 0 | #define gconf_client_get_int _gconf_client_get_int |
45 | 0 | #define gconf_client_get_float _gconf_client_get_float |
46 | 0 | #define gconf_client_get_list _gconf_client_get_list |
47 | 0 | #define gconf_client_set_bool _gconf_client_set_bool |
48 | 0 | #define gconf_client_set_string _gconf_client_set_string |
49 | 0 | #define gconf_client_set_int _gconf_client_set_int |
50 | 0 | #define gconf_client_set_float _gconf_client_set_float |
51 | 0 | #define gconf_client_unset _gconf_client_unset |
52 | | |
53 | | static PRLibrary *gconfLib = nullptr; |
54 | | |
55 | | typedef void (*nsGConfFunc)(); |
56 | | struct nsGConfDynamicFunction { |
57 | | const char *functionName; |
58 | | nsGConfFunc *function; |
59 | | }; |
60 | | |
61 | | nsGConfService::~nsGConfService() |
62 | 0 | { |
63 | 0 | if (mClient) |
64 | 0 | g_object_unref(mClient); |
65 | 0 |
|
66 | 0 | // We don't unload gconf here because liborbit uses atexit(). In addition to |
67 | 0 | // this, it's not a good idea to unload any gobject based library, as it |
68 | 0 | // leaves types registered in glib's type system |
69 | 0 | } |
70 | | |
71 | | nsresult |
72 | | nsGConfService::Init() |
73 | 0 | { |
74 | 0 | #define FUNC(name, type, params) { #name, (nsGConfFunc *)&_##name }, |
75 | 0 | static const nsGConfDynamicFunction kGConfSymbols[] = { |
76 | 0 | GCONF_FUNCTIONS |
77 | 0 | }; |
78 | 0 | #undef FUNC |
79 | 0 |
|
80 | 0 | if (NS_WARN_IF(XRE_IsContentProcess())) { |
81 | 0 | return NS_ERROR_SERVICE_NOT_AVAILABLE; |
82 | 0 | } |
83 | 0 | |
84 | 0 | if (!gconfLib) { |
85 | 0 | gconfLib = PR_LoadLibrary("libgconf-2.so.4"); |
86 | 0 | if (!gconfLib) |
87 | 0 | return NS_ERROR_FAILURE; |
88 | 0 | } |
89 | 0 | |
90 | 0 | for (auto GConfSymbol : kGConfSymbols) { |
91 | 0 | *GConfSymbol.function = |
92 | 0 | PR_FindFunctionSymbol(gconfLib, GConfSymbol.functionName); |
93 | 0 | if (!*GConfSymbol.function) { |
94 | 0 | return NS_ERROR_FAILURE; |
95 | 0 | } |
96 | 0 | } |
97 | 0 |
|
98 | 0 | mClient = gconf_client_get_default(); |
99 | 0 | return mClient ? NS_OK : NS_ERROR_FAILURE; |
100 | 0 | } |
101 | | |
102 | | NS_IMPL_ISUPPORTS(nsGConfService, nsIGConfService) |
103 | | |
104 | | NS_IMETHODIMP |
105 | | nsGConfService::GetBool(const nsACString &aKey, bool *aResult) |
106 | 0 | { |
107 | 0 | GError* error = nullptr; |
108 | 0 | *aResult = gconf_client_get_bool(mClient, PromiseFlatCString(aKey).get(), |
109 | 0 | &error); |
110 | 0 |
|
111 | 0 | if (error) { |
112 | 0 | g_error_free(error); |
113 | 0 | return NS_ERROR_FAILURE; |
114 | 0 | } |
115 | 0 | |
116 | 0 | return NS_OK; |
117 | 0 | } |
118 | | |
119 | | NS_IMETHODIMP |
120 | | nsGConfService::GetString(const nsACString &aKey, nsACString &aResult) |
121 | 0 | { |
122 | 0 | GError* error = nullptr; |
123 | 0 | gchar *result = gconf_client_get_string(mClient, |
124 | 0 | PromiseFlatCString(aKey).get(), |
125 | 0 | &error); |
126 | 0 |
|
127 | 0 | if (error) { |
128 | 0 | g_error_free(error); |
129 | 0 | return NS_ERROR_FAILURE; |
130 | 0 | } |
131 | 0 | |
132 | 0 | // We do a string copy here so that the caller doesn't need to worry about |
133 | 0 | // freeing the string with g_free(). |
134 | 0 | |
135 | 0 | aResult.Assign(result); |
136 | 0 | g_free(result); |
137 | 0 |
|
138 | 0 | return NS_OK; |
139 | 0 | } |
140 | | |
141 | | NS_IMETHODIMP |
142 | | nsGConfService::GetInt(const nsACString &aKey, int32_t* aResult) |
143 | 0 | { |
144 | 0 | GError* error = nullptr; |
145 | 0 | *aResult = gconf_client_get_int(mClient, PromiseFlatCString(aKey).get(), |
146 | 0 | &error); |
147 | 0 |
|
148 | 0 | if (error) { |
149 | 0 | g_error_free(error); |
150 | 0 | return NS_ERROR_FAILURE; |
151 | 0 | } |
152 | 0 | |
153 | 0 | return NS_OK; |
154 | 0 | } |
155 | | |
156 | | NS_IMETHODIMP |
157 | | nsGConfService::GetFloat(const nsACString &aKey, float* aResult) |
158 | 0 | { |
159 | 0 | GError* error = nullptr; |
160 | 0 | *aResult = gconf_client_get_float(mClient, PromiseFlatCString(aKey).get(), |
161 | 0 | &error); |
162 | 0 |
|
163 | 0 | if (error) { |
164 | 0 | g_error_free(error); |
165 | 0 | return NS_ERROR_FAILURE; |
166 | 0 | } |
167 | 0 | |
168 | 0 | return NS_OK; |
169 | 0 | } |
170 | | |
171 | | NS_IMETHODIMP |
172 | | nsGConfService::GetStringList(const nsACString &aKey, nsIArray** aResult) |
173 | 0 | { |
174 | 0 | nsCOMPtr<nsIMutableArray> items(do_CreateInstance(NS_ARRAY_CONTRACTID)); |
175 | 0 | if (!items) |
176 | 0 | return NS_ERROR_OUT_OF_MEMORY; |
177 | 0 | |
178 | 0 | GError* error = nullptr; |
179 | 0 | GSList* list = gconf_client_get_list(mClient, PromiseFlatCString(aKey).get(), |
180 | 0 | GCONF_VALUE_STRING, &error); |
181 | 0 | if (error) { |
182 | 0 | g_error_free(error); |
183 | 0 | return NS_ERROR_FAILURE; |
184 | 0 | } |
185 | 0 | |
186 | 0 | for (GSList* l = list; l; l = l->next) { |
187 | 0 | nsCOMPtr<nsISupportsString> obj(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID)); |
188 | 0 | if (!obj) { |
189 | 0 | g_slist_free(list); |
190 | 0 | return NS_ERROR_OUT_OF_MEMORY; |
191 | 0 | } |
192 | 0 | obj->SetData(NS_ConvertUTF8toUTF16((const char*)l->data)); |
193 | 0 | items->AppendElement(obj); |
194 | 0 | g_free(l->data); |
195 | 0 | } |
196 | 0 |
|
197 | 0 | g_slist_free(list); |
198 | 0 | items.forget(aResult); |
199 | 0 | return NS_OK; |
200 | 0 | } |
201 | | |
202 | | NS_IMETHODIMP |
203 | | nsGConfService::SetBool(const nsACString &aKey, bool aValue) |
204 | 0 | { |
205 | 0 | bool res = gconf_client_set_bool(mClient, PromiseFlatCString(aKey).get(), |
206 | 0 | aValue, nullptr); |
207 | 0 |
|
208 | 0 | return res ? NS_OK : NS_ERROR_FAILURE; |
209 | 0 | } |
210 | | |
211 | | NS_IMETHODIMP |
212 | | nsGConfService::SetString(const nsACString &aKey, const nsACString &aValue) |
213 | 0 | { |
214 | 0 | bool res = gconf_client_set_string(mClient, PromiseFlatCString(aKey).get(), |
215 | 0 | PromiseFlatCString(aValue).get(), |
216 | 0 | nullptr); |
217 | 0 |
|
218 | 0 | return res ? NS_OK : NS_ERROR_FAILURE; |
219 | 0 | } |
220 | | |
221 | | NS_IMETHODIMP |
222 | | nsGConfService::SetInt(const nsACString &aKey, int32_t aValue) |
223 | 0 | { |
224 | 0 | bool res = gconf_client_set_int(mClient, PromiseFlatCString(aKey).get(), |
225 | 0 | aValue, nullptr); |
226 | 0 |
|
227 | 0 | return res ? NS_OK : NS_ERROR_FAILURE; |
228 | 0 | } |
229 | | |
230 | | NS_IMETHODIMP |
231 | | nsGConfService::SetFloat(const nsACString &aKey, float aValue) |
232 | 0 | { |
233 | 0 | bool res = gconf_client_set_float(mClient, PromiseFlatCString(aKey).get(), |
234 | 0 | aValue, nullptr); |
235 | 0 |
|
236 | 0 | return res ? NS_OK : NS_ERROR_FAILURE; |
237 | 0 | } |
238 | | |
239 | | NS_IMETHODIMP |
240 | | nsGConfService::GetAppForProtocol(const nsACString &aScheme, bool *aEnabled, |
241 | | nsACString &aHandler) |
242 | 0 | { |
243 | 0 | nsAutoCString key("/desktop/gnome/url-handlers/"); |
244 | 0 | key.Append(aScheme); |
245 | 0 | key.AppendLiteral("/command"); |
246 | 0 |
|
247 | 0 | GError *err = nullptr; |
248 | 0 | gchar *command = gconf_client_get_string(mClient, key.get(), &err); |
249 | 0 | if (!err && command) { |
250 | 0 | key.ReplaceLiteral(key.Length() - 7, 7, "enabled"); |
251 | 0 | *aEnabled = gconf_client_get_bool(mClient, key.get(), &err); |
252 | 0 | } else { |
253 | 0 | *aEnabled = false; |
254 | 0 | } |
255 | 0 |
|
256 | 0 | aHandler.Assign(command); |
257 | 0 | g_free(command); |
258 | 0 |
|
259 | 0 | if (err) { |
260 | 0 | g_error_free(err); |
261 | 0 | return NS_ERROR_FAILURE; |
262 | 0 | } |
263 | 0 | |
264 | 0 | return NS_OK; |
265 | 0 | } |
266 | | |
267 | | NS_IMETHODIMP |
268 | | nsGConfService::HandlerRequiresTerminal(const nsACString &aScheme, |
269 | | bool *aResult) |
270 | 0 | { |
271 | 0 | nsAutoCString key("/desktop/gnome/url-handlers/"); |
272 | 0 | key.Append(aScheme); |
273 | 0 | key.AppendLiteral("/requires_terminal"); |
274 | 0 |
|
275 | 0 | GError *err = nullptr; |
276 | 0 | *aResult = gconf_client_get_bool(mClient, key.get(), &err); |
277 | 0 | if (err) { |
278 | 0 | g_error_free(err); |
279 | 0 | return NS_ERROR_FAILURE; |
280 | 0 | } |
281 | 0 | |
282 | 0 | return NS_OK; |
283 | 0 | } |
284 | | |
285 | | NS_IMETHODIMP |
286 | | nsGConfService::SetAppForProtocol(const nsACString &aScheme, |
287 | | const nsACString &aCommand) |
288 | 0 | { |
289 | 0 | nsAutoCString key("/desktop/gnome/url-handlers/"); |
290 | 0 | key.Append(aScheme); |
291 | 0 | key.AppendLiteral("/command"); |
292 | 0 |
|
293 | 0 | bool res = gconf_client_set_string(mClient, key.get(), |
294 | 0 | PromiseFlatCString(aCommand).get(), |
295 | 0 | nullptr); |
296 | 0 | if (res) { |
297 | 0 | key.ReplaceLiteral(key.Length() - 7, 7, "enabled"); |
298 | 0 | res = gconf_client_set_bool(mClient, key.get(), true, nullptr); |
299 | 0 | if (res) { |
300 | 0 | key.ReplaceLiteral(key.Length() - 7, 7, "needs_terminal"); |
301 | 0 | res = gconf_client_set_bool(mClient, key.get(), false, nullptr); |
302 | 0 | if (res) { |
303 | 0 | key.ReplaceLiteral(key.Length() - 14, 14, "command-id"); |
304 | 0 | res = gconf_client_unset(mClient, key.get(), nullptr); |
305 | 0 | } |
306 | 0 | } |
307 | 0 | } |
308 | 0 |
|
309 | 0 | return res ? NS_OK : NS_ERROR_FAILURE; |
310 | 0 | } |