1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is the Mozilla GNOME integration code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * IBM Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 2004
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Brian Ryner <bryner@brianryner.com>
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #include "mozilla/Util.h"
40 : #include "nsGConfService.h"
41 : #include "nsStringAPI.h"
42 : #include "nsCOMPtr.h"
43 : #include "nsComponentManagerUtils.h"
44 : #include "nsISupportsPrimitives.h"
45 : #include "nsIMutableArray.h"
46 : #include "prlink.h"
47 :
48 : #include <gconf/gconf-client.h>
49 :
50 : using namespace mozilla;
51 :
52 : #define GCONF_FUNCTIONS \
53 : FUNC(gconf_client_get_default, GConfClient*, (void)) \
54 : FUNC(gconf_client_get_bool, gboolean, (GConfClient*, const gchar*, GError**)) \
55 : FUNC(gconf_client_get_string, gchar*, (GConfClient*, const gchar*, GError**)) \
56 : FUNC(gconf_client_get_int, gint, (GConfClient*, const gchar*, GError**)) \
57 : FUNC(gconf_client_get_float, gdouble, (GConfClient*, const gchar*, GError**)) \
58 : FUNC(gconf_client_get_list, GSList*, (GConfClient*, const gchar*, GConfValueType, GError**)) \
59 : FUNC(gconf_client_set_bool, gboolean, (GConfClient*, const gchar*, gboolean, GError**)) \
60 : FUNC(gconf_client_set_string, gboolean, (GConfClient*, const gchar*, const gchar*, GError**)) \
61 : FUNC(gconf_client_set_int, gboolean, (GConfClient*, const gchar*, gint, GError**)) \
62 : FUNC(gconf_client_set_float, gboolean, (GConfClient*, const gchar*, gdouble, GError**)) \
63 : FUNC(gconf_client_unset, gboolean, (GConfClient*, const gchar*, GError**))
64 :
65 : #define FUNC(name, type, params) \
66 : typedef type (*_##name##_fn) params; \
67 : static _##name##_fn _##name;
68 :
69 : GCONF_FUNCTIONS
70 :
71 : #undef FUNC
72 :
73 : #define gconf_client_get_default _gconf_client_get_default
74 : #define gconf_client_get_bool _gconf_client_get_bool
75 : #define gconf_client_get_string _gconf_client_get_string
76 : #define gconf_client_get_int _gconf_client_get_int
77 : #define gconf_client_get_float _gconf_client_get_float
78 : #define gconf_client_get_list _gconf_client_get_list
79 : #define gconf_client_set_bool _gconf_client_set_bool
80 : #define gconf_client_set_string _gconf_client_set_string
81 : #define gconf_client_set_int _gconf_client_set_int
82 : #define gconf_client_set_float _gconf_client_set_float
83 : #define gconf_client_unset _gconf_client_unset
84 :
85 : static PRLibrary *gconfLib = nsnull;
86 :
87 : typedef void (*nsGConfFunc)();
88 : struct nsGConfDynamicFunction {
89 : const char *functionName;
90 : nsGConfFunc *function;
91 : };
92 :
93 272 : nsGConfService::~nsGConfService()
94 : {
95 272 : if (mClient)
96 272 : g_object_unref(mClient);
97 :
98 : // We don't unload gconf here because liborbit uses atexit(). In addition to
99 : // this, it's not a good idea to unload any gobject based library, as it
100 : // leaves types registered in glib's type system
101 272 : }
102 :
103 : nsresult
104 272 : nsGConfService::Init()
105 : {
106 : #define FUNC(name, type, params) { #name, (nsGConfFunc *)&_##name },
107 : static const nsGConfDynamicFunction kGConfSymbols[] = {
108 : GCONF_FUNCTIONS
109 : };
110 : #undef FUNC
111 :
112 272 : if (!gconfLib) {
113 272 : gconfLib = PR_LoadLibrary("libgconf-2.so.4");
114 272 : if (!gconfLib)
115 0 : return NS_ERROR_FAILURE;
116 : }
117 :
118 3264 : for (PRUint32 i = 0; i < ArrayLength(kGConfSymbols); i++) {
119 : *kGConfSymbols[i].function =
120 2992 : PR_FindFunctionSymbol(gconfLib, kGConfSymbols[i].functionName);
121 2992 : if (!*kGConfSymbols[i].function) {
122 0 : return NS_ERROR_FAILURE;
123 : }
124 : }
125 :
126 272 : mClient = gconf_client_get_default();
127 272 : return mClient ? NS_OK : NS_ERROR_FAILURE;
128 : }
129 :
130 3032 : NS_IMPL_ISUPPORTS1(nsGConfService, nsIGConfService)
131 :
132 : NS_IMETHODIMP
133 3417 : nsGConfService::GetBool(const nsACString &aKey, bool *aResult)
134 : {
135 3417 : GError* error = nsnull;
136 3417 : *aResult = gconf_client_get_bool(mClient, PromiseFlatCString(aKey).get(),
137 3417 : &error);
138 :
139 3417 : if (error) {
140 0 : g_error_free(error);
141 0 : return NS_ERROR_FAILURE;
142 : }
143 :
144 3417 : return NS_OK;
145 : }
146 :
147 : NS_IMETHODIMP
148 7131 : nsGConfService::GetString(const nsACString &aKey, nsACString &aResult)
149 : {
150 7131 : GError* error = nsnull;
151 : gchar *result = gconf_client_get_string(mClient,
152 7131 : PromiseFlatCString(aKey).get(),
153 7131 : &error);
154 :
155 7131 : if (error) {
156 0 : g_error_free(error);
157 0 : return NS_ERROR_FAILURE;
158 : }
159 :
160 : // We do a string copy here so that the caller doesn't need to worry about
161 : // freeing the string with g_free().
162 :
163 7131 : aResult.Assign(result);
164 7131 : g_free(result);
165 :
166 7131 : return NS_OK;
167 : }
168 :
169 : NS_IMETHODIMP
170 0 : nsGConfService::GetInt(const nsACString &aKey, PRInt32* aResult)
171 : {
172 0 : GError* error = nsnull;
173 0 : *aResult = gconf_client_get_int(mClient, PromiseFlatCString(aKey).get(),
174 0 : &error);
175 :
176 0 : if (error) {
177 0 : g_error_free(error);
178 0 : return NS_ERROR_FAILURE;
179 : }
180 :
181 0 : return NS_OK;
182 : }
183 :
184 : NS_IMETHODIMP
185 0 : nsGConfService::GetFloat(const nsACString &aKey, float* aResult)
186 : {
187 0 : GError* error = nsnull;
188 0 : *aResult = gconf_client_get_float(mClient, PromiseFlatCString(aKey).get(),
189 0 : &error);
190 :
191 0 : if (error) {
192 0 : g_error_free(error);
193 0 : return NS_ERROR_FAILURE;
194 : }
195 :
196 0 : return NS_OK;
197 : }
198 :
199 : NS_IMETHODIMP
200 0 : nsGConfService::GetStringList(const nsACString &aKey, nsIArray** aResult)
201 : {
202 0 : nsCOMPtr<nsIMutableArray> items(do_CreateInstance(NS_ARRAY_CONTRACTID));
203 0 : if (!items)
204 0 : return NS_ERROR_OUT_OF_MEMORY;
205 :
206 0 : GError* error = nsnull;
207 0 : GSList* list = gconf_client_get_list(mClient, PromiseFlatCString(aKey).get(),
208 0 : GCONF_VALUE_STRING, &error);
209 0 : if (error) {
210 0 : g_error_free(error);
211 0 : return NS_ERROR_FAILURE;
212 : }
213 :
214 0 : for (GSList* l = list; l; l = l->next) {
215 0 : nsCOMPtr<nsISupportsString> obj(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID));
216 0 : if (!obj) {
217 0 : g_slist_free(list);
218 0 : return NS_ERROR_OUT_OF_MEMORY;
219 : }
220 0 : obj->SetData(NS_ConvertUTF8toUTF16((const char*)l->data));
221 0 : items->AppendElement(obj, false);
222 0 : g_free(l->data);
223 : }
224 :
225 0 : g_slist_free(list);
226 0 : NS_ADDREF(*aResult = items);
227 0 : return NS_OK;
228 : }
229 :
230 : NS_IMETHODIMP
231 0 : nsGConfService::SetBool(const nsACString &aKey, bool aValue)
232 : {
233 0 : bool res = gconf_client_set_bool(mClient, PromiseFlatCString(aKey).get(),
234 0 : aValue, nsnull);
235 :
236 0 : return res ? NS_OK : NS_ERROR_FAILURE;
237 : }
238 :
239 : NS_IMETHODIMP
240 25 : nsGConfService::SetString(const nsACString &aKey, const nsACString &aValue)
241 : {
242 25 : bool res = gconf_client_set_string(mClient, PromiseFlatCString(aKey).get(),
243 25 : PromiseFlatCString(aValue).get(),
244 25 : nsnull);
245 :
246 25 : return res ? NS_OK : NS_ERROR_FAILURE;
247 : }
248 :
249 : NS_IMETHODIMP
250 0 : nsGConfService::SetInt(const nsACString &aKey, PRInt32 aValue)
251 : {
252 0 : bool res = gconf_client_set_int(mClient, PromiseFlatCString(aKey).get(),
253 0 : aValue, nsnull);
254 :
255 0 : return res ? NS_OK : NS_ERROR_FAILURE;
256 : }
257 :
258 : NS_IMETHODIMP
259 0 : nsGConfService::SetFloat(const nsACString &aKey, float aValue)
260 : {
261 0 : bool res = gconf_client_set_float(mClient, PromiseFlatCString(aKey).get(),
262 0 : aValue, nsnull);
263 :
264 0 : return res ? NS_OK : NS_ERROR_FAILURE;
265 : }
266 :
267 : NS_IMETHODIMP
268 37 : nsGConfService::GetAppForProtocol(const nsACString &aScheme, bool *aEnabled,
269 : nsACString &aHandler)
270 : {
271 74 : nsCAutoString key("/desktop/gnome/url-handlers/");
272 37 : key.Append(aScheme);
273 37 : key.Append("/command");
274 :
275 37 : GError *err = nsnull;
276 37 : gchar *command = gconf_client_get_string(mClient, key.get(), &err);
277 37 : if (!err && command) {
278 18 : key.Replace(key.Length() - 7, 7, NS_LITERAL_CSTRING("enabled"));
279 18 : *aEnabled = gconf_client_get_bool(mClient, key.get(), &err);
280 : } else {
281 19 : *aEnabled = false;
282 : }
283 :
284 37 : aHandler.Assign(command);
285 37 : g_free(command);
286 :
287 37 : if (err) {
288 0 : g_error_free(err);
289 0 : return NS_ERROR_FAILURE;
290 : }
291 :
292 37 : return NS_OK;
293 : }
294 :
295 : NS_IMETHODIMP
296 0 : nsGConfService::HandlerRequiresTerminal(const nsACString &aScheme,
297 : bool *aResult)
298 : {
299 0 : nsCAutoString key("/desktop/gnome/url-handlers/");
300 0 : key.Append(aScheme);
301 0 : key.Append("/requires_terminal");
302 :
303 0 : GError *err = nsnull;
304 0 : *aResult = gconf_client_get_bool(mClient, key.get(), &err);
305 0 : if (err) {
306 0 : g_error_free(err);
307 0 : return NS_ERROR_FAILURE;
308 : }
309 :
310 0 : return NS_OK;
311 : }
312 :
313 : NS_IMETHODIMP
314 0 : nsGConfService::SetAppForProtocol(const nsACString &aScheme,
315 : const nsACString &aCommand)
316 : {
317 0 : nsCAutoString key("/desktop/gnome/url-handlers/");
318 0 : key.Append(aScheme);
319 0 : key.Append("/command");
320 :
321 : bool res = gconf_client_set_string(mClient, key.get(),
322 0 : PromiseFlatCString(aCommand).get(),
323 0 : nsnull);
324 0 : if (res) {
325 0 : key.Replace(key.Length() - 7, 7, NS_LITERAL_CSTRING("enabled"));
326 0 : res = gconf_client_set_bool(mClient, key.get(), true, nsnull);
327 0 : if (res) {
328 0 : key.Replace(key.Length() - 7, 7, NS_LITERAL_CSTRING("needs_terminal"));
329 0 : res = gconf_client_set_bool(mClient, key.get(), false, nsnull);
330 0 : if (res) {
331 0 : key.Replace(key.Length() - 14, 14, NS_LITERAL_CSTRING("command-id"));
332 0 : res = gconf_client_unset(mClient, key.get(), nsnull);
333 : }
334 : }
335 : }
336 :
337 0 : return res ? NS_OK : NS_ERROR_FAILURE;
338 : }
|