1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/system/gnome/nsGConfService.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,305 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "mozilla/ArrayUtils.h" 1.10 +#include "nsGConfService.h" 1.11 +#include "nsStringAPI.h" 1.12 +#include "nsCOMPtr.h" 1.13 +#include "nsComponentManagerUtils.h" 1.14 +#include "nsISupportsPrimitives.h" 1.15 +#include "nsIMutableArray.h" 1.16 +#include "prlink.h" 1.17 + 1.18 +#include <gconf/gconf-client.h> 1.19 + 1.20 +using namespace mozilla; 1.21 + 1.22 +#define GCONF_FUNCTIONS \ 1.23 + FUNC(gconf_client_get_default, GConfClient*, (void)) \ 1.24 + FUNC(gconf_client_get_bool, gboolean, (GConfClient*, const gchar*, GError**)) \ 1.25 + FUNC(gconf_client_get_string, gchar*, (GConfClient*, const gchar*, GError**)) \ 1.26 + FUNC(gconf_client_get_int, gint, (GConfClient*, const gchar*, GError**)) \ 1.27 + FUNC(gconf_client_get_float, gdouble, (GConfClient*, const gchar*, GError**)) \ 1.28 + FUNC(gconf_client_get_list, GSList*, (GConfClient*, const gchar*, GConfValueType, GError**)) \ 1.29 + FUNC(gconf_client_set_bool, gboolean, (GConfClient*, const gchar*, gboolean, GError**)) \ 1.30 + FUNC(gconf_client_set_string, gboolean, (GConfClient*, const gchar*, const gchar*, GError**)) \ 1.31 + FUNC(gconf_client_set_int, gboolean, (GConfClient*, const gchar*, gint, GError**)) \ 1.32 + FUNC(gconf_client_set_float, gboolean, (GConfClient*, const gchar*, gdouble, GError**)) \ 1.33 + FUNC(gconf_client_unset, gboolean, (GConfClient*, const gchar*, GError**)) 1.34 + 1.35 +#define FUNC(name, type, params) \ 1.36 + typedef type (*_##name##_fn) params; \ 1.37 + static _##name##_fn _##name; 1.38 + 1.39 +GCONF_FUNCTIONS 1.40 + 1.41 +#undef FUNC 1.42 + 1.43 +#define gconf_client_get_default _gconf_client_get_default 1.44 +#define gconf_client_get_bool _gconf_client_get_bool 1.45 +#define gconf_client_get_string _gconf_client_get_string 1.46 +#define gconf_client_get_int _gconf_client_get_int 1.47 +#define gconf_client_get_float _gconf_client_get_float 1.48 +#define gconf_client_get_list _gconf_client_get_list 1.49 +#define gconf_client_set_bool _gconf_client_set_bool 1.50 +#define gconf_client_set_string _gconf_client_set_string 1.51 +#define gconf_client_set_int _gconf_client_set_int 1.52 +#define gconf_client_set_float _gconf_client_set_float 1.53 +#define gconf_client_unset _gconf_client_unset 1.54 + 1.55 +static PRLibrary *gconfLib = nullptr; 1.56 + 1.57 +typedef void (*nsGConfFunc)(); 1.58 +struct nsGConfDynamicFunction { 1.59 + const char *functionName; 1.60 + nsGConfFunc *function; 1.61 +}; 1.62 + 1.63 +nsGConfService::~nsGConfService() 1.64 +{ 1.65 + if (mClient) 1.66 + g_object_unref(mClient); 1.67 + 1.68 + // We don't unload gconf here because liborbit uses atexit(). In addition to 1.69 + // this, it's not a good idea to unload any gobject based library, as it 1.70 + // leaves types registered in glib's type system 1.71 +} 1.72 + 1.73 +nsresult 1.74 +nsGConfService::Init() 1.75 +{ 1.76 +#define FUNC(name, type, params) { #name, (nsGConfFunc *)&_##name }, 1.77 + static const nsGConfDynamicFunction kGConfSymbols[] = { 1.78 + GCONF_FUNCTIONS 1.79 + }; 1.80 +#undef FUNC 1.81 + 1.82 + if (!gconfLib) { 1.83 + gconfLib = PR_LoadLibrary("libgconf-2.so.4"); 1.84 + if (!gconfLib) 1.85 + return NS_ERROR_FAILURE; 1.86 + } 1.87 + 1.88 + for (uint32_t i = 0; i < ArrayLength(kGConfSymbols); i++) { 1.89 + *kGConfSymbols[i].function = 1.90 + PR_FindFunctionSymbol(gconfLib, kGConfSymbols[i].functionName); 1.91 + if (!*kGConfSymbols[i].function) { 1.92 + return NS_ERROR_FAILURE; 1.93 + } 1.94 + } 1.95 + 1.96 + mClient = gconf_client_get_default(); 1.97 + return mClient ? NS_OK : NS_ERROR_FAILURE; 1.98 +} 1.99 + 1.100 +NS_IMPL_ISUPPORTS(nsGConfService, nsIGConfService) 1.101 + 1.102 +NS_IMETHODIMP 1.103 +nsGConfService::GetBool(const nsACString &aKey, bool *aResult) 1.104 +{ 1.105 + GError* error = nullptr; 1.106 + *aResult = gconf_client_get_bool(mClient, PromiseFlatCString(aKey).get(), 1.107 + &error); 1.108 + 1.109 + if (error) { 1.110 + g_error_free(error); 1.111 + return NS_ERROR_FAILURE; 1.112 + } 1.113 + 1.114 + return NS_OK; 1.115 +} 1.116 + 1.117 +NS_IMETHODIMP 1.118 +nsGConfService::GetString(const nsACString &aKey, nsACString &aResult) 1.119 +{ 1.120 + GError* error = nullptr; 1.121 + gchar *result = gconf_client_get_string(mClient, 1.122 + PromiseFlatCString(aKey).get(), 1.123 + &error); 1.124 + 1.125 + if (error) { 1.126 + g_error_free(error); 1.127 + return NS_ERROR_FAILURE; 1.128 + } 1.129 + 1.130 + // We do a string copy here so that the caller doesn't need to worry about 1.131 + // freeing the string with g_free(). 1.132 + 1.133 + aResult.Assign(result); 1.134 + g_free(result); 1.135 + 1.136 + return NS_OK; 1.137 +} 1.138 + 1.139 +NS_IMETHODIMP 1.140 +nsGConfService::GetInt(const nsACString &aKey, int32_t* aResult) 1.141 +{ 1.142 + GError* error = nullptr; 1.143 + *aResult = gconf_client_get_int(mClient, PromiseFlatCString(aKey).get(), 1.144 + &error); 1.145 + 1.146 + if (error) { 1.147 + g_error_free(error); 1.148 + return NS_ERROR_FAILURE; 1.149 + } 1.150 + 1.151 + return NS_OK; 1.152 +} 1.153 + 1.154 +NS_IMETHODIMP 1.155 +nsGConfService::GetFloat(const nsACString &aKey, float* aResult) 1.156 +{ 1.157 + GError* error = nullptr; 1.158 + *aResult = gconf_client_get_float(mClient, PromiseFlatCString(aKey).get(), 1.159 + &error); 1.160 + 1.161 + if (error) { 1.162 + g_error_free(error); 1.163 + return NS_ERROR_FAILURE; 1.164 + } 1.165 + 1.166 + return NS_OK; 1.167 +} 1.168 + 1.169 +NS_IMETHODIMP 1.170 +nsGConfService::GetStringList(const nsACString &aKey, nsIArray** aResult) 1.171 +{ 1.172 + nsCOMPtr<nsIMutableArray> items(do_CreateInstance(NS_ARRAY_CONTRACTID)); 1.173 + if (!items) 1.174 + return NS_ERROR_OUT_OF_MEMORY; 1.175 + 1.176 + GError* error = nullptr; 1.177 + GSList* list = gconf_client_get_list(mClient, PromiseFlatCString(aKey).get(), 1.178 + GCONF_VALUE_STRING, &error); 1.179 + if (error) { 1.180 + g_error_free(error); 1.181 + return NS_ERROR_FAILURE; 1.182 + } 1.183 + 1.184 + for (GSList* l = list; l; l = l->next) { 1.185 + nsCOMPtr<nsISupportsString> obj(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID)); 1.186 + if (!obj) { 1.187 + g_slist_free(list); 1.188 + return NS_ERROR_OUT_OF_MEMORY; 1.189 + } 1.190 + obj->SetData(NS_ConvertUTF8toUTF16((const char*)l->data)); 1.191 + items->AppendElement(obj, false); 1.192 + g_free(l->data); 1.193 + } 1.194 + 1.195 + g_slist_free(list); 1.196 + NS_ADDREF(*aResult = items); 1.197 + return NS_OK; 1.198 +} 1.199 + 1.200 +NS_IMETHODIMP 1.201 +nsGConfService::SetBool(const nsACString &aKey, bool aValue) 1.202 +{ 1.203 + bool res = gconf_client_set_bool(mClient, PromiseFlatCString(aKey).get(), 1.204 + aValue, nullptr); 1.205 + 1.206 + return res ? NS_OK : NS_ERROR_FAILURE; 1.207 +} 1.208 + 1.209 +NS_IMETHODIMP 1.210 +nsGConfService::SetString(const nsACString &aKey, const nsACString &aValue) 1.211 +{ 1.212 + bool res = gconf_client_set_string(mClient, PromiseFlatCString(aKey).get(), 1.213 + PromiseFlatCString(aValue).get(), 1.214 + nullptr); 1.215 + 1.216 + return res ? NS_OK : NS_ERROR_FAILURE; 1.217 +} 1.218 + 1.219 +NS_IMETHODIMP 1.220 +nsGConfService::SetInt(const nsACString &aKey, int32_t aValue) 1.221 +{ 1.222 + bool res = gconf_client_set_int(mClient, PromiseFlatCString(aKey).get(), 1.223 + aValue, nullptr); 1.224 + 1.225 + return res ? NS_OK : NS_ERROR_FAILURE; 1.226 +} 1.227 + 1.228 +NS_IMETHODIMP 1.229 +nsGConfService::SetFloat(const nsACString &aKey, float aValue) 1.230 +{ 1.231 + bool res = gconf_client_set_float(mClient, PromiseFlatCString(aKey).get(), 1.232 + aValue, nullptr); 1.233 + 1.234 + return res ? NS_OK : NS_ERROR_FAILURE; 1.235 +} 1.236 + 1.237 +NS_IMETHODIMP 1.238 +nsGConfService::GetAppForProtocol(const nsACString &aScheme, bool *aEnabled, 1.239 + nsACString &aHandler) 1.240 +{ 1.241 + nsAutoCString key("/desktop/gnome/url-handlers/"); 1.242 + key.Append(aScheme); 1.243 + key.Append("/command"); 1.244 + 1.245 + GError *err = nullptr; 1.246 + gchar *command = gconf_client_get_string(mClient, key.get(), &err); 1.247 + if (!err && command) { 1.248 + key.Replace(key.Length() - 7, 7, NS_LITERAL_CSTRING("enabled")); 1.249 + *aEnabled = gconf_client_get_bool(mClient, key.get(), &err); 1.250 + } else { 1.251 + *aEnabled = false; 1.252 + } 1.253 + 1.254 + aHandler.Assign(command); 1.255 + g_free(command); 1.256 + 1.257 + if (err) { 1.258 + g_error_free(err); 1.259 + return NS_ERROR_FAILURE; 1.260 + } 1.261 + 1.262 + return NS_OK; 1.263 +} 1.264 + 1.265 +NS_IMETHODIMP 1.266 +nsGConfService::HandlerRequiresTerminal(const nsACString &aScheme, 1.267 + bool *aResult) 1.268 +{ 1.269 + nsAutoCString key("/desktop/gnome/url-handlers/"); 1.270 + key.Append(aScheme); 1.271 + key.Append("/requires_terminal"); 1.272 + 1.273 + GError *err = nullptr; 1.274 + *aResult = gconf_client_get_bool(mClient, key.get(), &err); 1.275 + if (err) { 1.276 + g_error_free(err); 1.277 + return NS_ERROR_FAILURE; 1.278 + } 1.279 + 1.280 + return NS_OK; 1.281 +} 1.282 + 1.283 +NS_IMETHODIMP 1.284 +nsGConfService::SetAppForProtocol(const nsACString &aScheme, 1.285 + const nsACString &aCommand) 1.286 +{ 1.287 + nsAutoCString key("/desktop/gnome/url-handlers/"); 1.288 + key.Append(aScheme); 1.289 + key.Append("/command"); 1.290 + 1.291 + bool res = gconf_client_set_string(mClient, key.get(), 1.292 + PromiseFlatCString(aCommand).get(), 1.293 + nullptr); 1.294 + if (res) { 1.295 + key.Replace(key.Length() - 7, 7, NS_LITERAL_CSTRING("enabled")); 1.296 + res = gconf_client_set_bool(mClient, key.get(), true, nullptr); 1.297 + if (res) { 1.298 + key.Replace(key.Length() - 7, 7, NS_LITERAL_CSTRING("needs_terminal")); 1.299 + res = gconf_client_set_bool(mClient, key.get(), false, nullptr); 1.300 + if (res) { 1.301 + key.Replace(key.Length() - 14, 14, NS_LITERAL_CSTRING("command-id")); 1.302 + res = gconf_client_unset(mClient, key.get(), nullptr); 1.303 + } 1.304 + } 1.305 + } 1.306 + 1.307 + return res ? NS_OK : NS_ERROR_FAILURE; 1.308 +}