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