Coverage Report

Created: 2018-09-25 14:53

/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
}