michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "mozilla/ArrayUtils.h" michael@0: #include "nsGConfService.h" michael@0: #include "nsStringAPI.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsComponentManagerUtils.h" michael@0: #include "nsISupportsPrimitives.h" michael@0: #include "nsIMutableArray.h" michael@0: #include "prlink.h" michael@0: michael@0: #include michael@0: michael@0: using namespace mozilla; michael@0: michael@0: #define GCONF_FUNCTIONS \ michael@0: FUNC(gconf_client_get_default, GConfClient*, (void)) \ michael@0: FUNC(gconf_client_get_bool, gboolean, (GConfClient*, const gchar*, GError**)) \ michael@0: FUNC(gconf_client_get_string, gchar*, (GConfClient*, const gchar*, GError**)) \ michael@0: FUNC(gconf_client_get_int, gint, (GConfClient*, const gchar*, GError**)) \ michael@0: FUNC(gconf_client_get_float, gdouble, (GConfClient*, const gchar*, GError**)) \ michael@0: FUNC(gconf_client_get_list, GSList*, (GConfClient*, const gchar*, GConfValueType, GError**)) \ michael@0: FUNC(gconf_client_set_bool, gboolean, (GConfClient*, const gchar*, gboolean, GError**)) \ michael@0: FUNC(gconf_client_set_string, gboolean, (GConfClient*, const gchar*, const gchar*, GError**)) \ michael@0: FUNC(gconf_client_set_int, gboolean, (GConfClient*, const gchar*, gint, GError**)) \ michael@0: FUNC(gconf_client_set_float, gboolean, (GConfClient*, const gchar*, gdouble, GError**)) \ michael@0: FUNC(gconf_client_unset, gboolean, (GConfClient*, const gchar*, GError**)) michael@0: michael@0: #define FUNC(name, type, params) \ michael@0: typedef type (*_##name##_fn) params; \ michael@0: static _##name##_fn _##name; michael@0: michael@0: GCONF_FUNCTIONS michael@0: michael@0: #undef FUNC michael@0: michael@0: #define gconf_client_get_default _gconf_client_get_default michael@0: #define gconf_client_get_bool _gconf_client_get_bool michael@0: #define gconf_client_get_string _gconf_client_get_string michael@0: #define gconf_client_get_int _gconf_client_get_int michael@0: #define gconf_client_get_float _gconf_client_get_float michael@0: #define gconf_client_get_list _gconf_client_get_list michael@0: #define gconf_client_set_bool _gconf_client_set_bool michael@0: #define gconf_client_set_string _gconf_client_set_string michael@0: #define gconf_client_set_int _gconf_client_set_int michael@0: #define gconf_client_set_float _gconf_client_set_float michael@0: #define gconf_client_unset _gconf_client_unset michael@0: michael@0: static PRLibrary *gconfLib = nullptr; michael@0: michael@0: typedef void (*nsGConfFunc)(); michael@0: struct nsGConfDynamicFunction { michael@0: const char *functionName; michael@0: nsGConfFunc *function; michael@0: }; michael@0: michael@0: nsGConfService::~nsGConfService() michael@0: { michael@0: if (mClient) michael@0: g_object_unref(mClient); michael@0: michael@0: // We don't unload gconf here because liborbit uses atexit(). In addition to michael@0: // this, it's not a good idea to unload any gobject based library, as it michael@0: // leaves types registered in glib's type system michael@0: } michael@0: michael@0: nsresult michael@0: nsGConfService::Init() michael@0: { michael@0: #define FUNC(name, type, params) { #name, (nsGConfFunc *)&_##name }, michael@0: static const nsGConfDynamicFunction kGConfSymbols[] = { michael@0: GCONF_FUNCTIONS michael@0: }; michael@0: #undef FUNC michael@0: michael@0: if (!gconfLib) { michael@0: gconfLib = PR_LoadLibrary("libgconf-2.so.4"); michael@0: if (!gconfLib) michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: for (uint32_t i = 0; i < ArrayLength(kGConfSymbols); i++) { michael@0: *kGConfSymbols[i].function = michael@0: PR_FindFunctionSymbol(gconfLib, kGConfSymbols[i].functionName); michael@0: if (!*kGConfSymbols[i].function) { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: } michael@0: michael@0: mClient = gconf_client_get_default(); michael@0: return mClient ? NS_OK : NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS(nsGConfService, nsIGConfService) michael@0: michael@0: NS_IMETHODIMP michael@0: nsGConfService::GetBool(const nsACString &aKey, bool *aResult) michael@0: { michael@0: GError* error = nullptr; michael@0: *aResult = gconf_client_get_bool(mClient, PromiseFlatCString(aKey).get(), michael@0: &error); michael@0: michael@0: if (error) { michael@0: g_error_free(error); michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsGConfService::GetString(const nsACString &aKey, nsACString &aResult) michael@0: { michael@0: GError* error = nullptr; michael@0: gchar *result = gconf_client_get_string(mClient, michael@0: PromiseFlatCString(aKey).get(), michael@0: &error); michael@0: michael@0: if (error) { michael@0: g_error_free(error); michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: // We do a string copy here so that the caller doesn't need to worry about michael@0: // freeing the string with g_free(). michael@0: michael@0: aResult.Assign(result); michael@0: g_free(result); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsGConfService::GetInt(const nsACString &aKey, int32_t* aResult) michael@0: { michael@0: GError* error = nullptr; michael@0: *aResult = gconf_client_get_int(mClient, PromiseFlatCString(aKey).get(), michael@0: &error); michael@0: michael@0: if (error) { michael@0: g_error_free(error); michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsGConfService::GetFloat(const nsACString &aKey, float* aResult) michael@0: { michael@0: GError* error = nullptr; michael@0: *aResult = gconf_client_get_float(mClient, PromiseFlatCString(aKey).get(), michael@0: &error); michael@0: michael@0: if (error) { michael@0: g_error_free(error); michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsGConfService::GetStringList(const nsACString &aKey, nsIArray** aResult) michael@0: { michael@0: nsCOMPtr items(do_CreateInstance(NS_ARRAY_CONTRACTID)); michael@0: if (!items) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: GError* error = nullptr; michael@0: GSList* list = gconf_client_get_list(mClient, PromiseFlatCString(aKey).get(), michael@0: GCONF_VALUE_STRING, &error); michael@0: if (error) { michael@0: g_error_free(error); michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: for (GSList* l = list; l; l = l->next) { michael@0: nsCOMPtr obj(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID)); michael@0: if (!obj) { michael@0: g_slist_free(list); michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: obj->SetData(NS_ConvertUTF8toUTF16((const char*)l->data)); michael@0: items->AppendElement(obj, false); michael@0: g_free(l->data); michael@0: } michael@0: michael@0: g_slist_free(list); michael@0: NS_ADDREF(*aResult = items); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsGConfService::SetBool(const nsACString &aKey, bool aValue) michael@0: { michael@0: bool res = gconf_client_set_bool(mClient, PromiseFlatCString(aKey).get(), michael@0: aValue, nullptr); michael@0: michael@0: return res ? NS_OK : NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsGConfService::SetString(const nsACString &aKey, const nsACString &aValue) michael@0: { michael@0: bool res = gconf_client_set_string(mClient, PromiseFlatCString(aKey).get(), michael@0: PromiseFlatCString(aValue).get(), michael@0: nullptr); michael@0: michael@0: return res ? NS_OK : NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsGConfService::SetInt(const nsACString &aKey, int32_t aValue) michael@0: { michael@0: bool res = gconf_client_set_int(mClient, PromiseFlatCString(aKey).get(), michael@0: aValue, nullptr); michael@0: michael@0: return res ? NS_OK : NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsGConfService::SetFloat(const nsACString &aKey, float aValue) michael@0: { michael@0: bool res = gconf_client_set_float(mClient, PromiseFlatCString(aKey).get(), michael@0: aValue, nullptr); michael@0: michael@0: return res ? NS_OK : NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsGConfService::GetAppForProtocol(const nsACString &aScheme, bool *aEnabled, michael@0: nsACString &aHandler) michael@0: { michael@0: nsAutoCString key("/desktop/gnome/url-handlers/"); michael@0: key.Append(aScheme); michael@0: key.Append("/command"); michael@0: michael@0: GError *err = nullptr; michael@0: gchar *command = gconf_client_get_string(mClient, key.get(), &err); michael@0: if (!err && command) { michael@0: key.Replace(key.Length() - 7, 7, NS_LITERAL_CSTRING("enabled")); michael@0: *aEnabled = gconf_client_get_bool(mClient, key.get(), &err); michael@0: } else { michael@0: *aEnabled = false; michael@0: } michael@0: michael@0: aHandler.Assign(command); michael@0: g_free(command); michael@0: michael@0: if (err) { michael@0: g_error_free(err); michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsGConfService::HandlerRequiresTerminal(const nsACString &aScheme, michael@0: bool *aResult) michael@0: { michael@0: nsAutoCString key("/desktop/gnome/url-handlers/"); michael@0: key.Append(aScheme); michael@0: key.Append("/requires_terminal"); michael@0: michael@0: GError *err = nullptr; michael@0: *aResult = gconf_client_get_bool(mClient, key.get(), &err); michael@0: if (err) { michael@0: g_error_free(err); michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsGConfService::SetAppForProtocol(const nsACString &aScheme, michael@0: const nsACString &aCommand) michael@0: { michael@0: nsAutoCString key("/desktop/gnome/url-handlers/"); michael@0: key.Append(aScheme); michael@0: key.Append("/command"); michael@0: michael@0: bool res = gconf_client_set_string(mClient, key.get(), michael@0: PromiseFlatCString(aCommand).get(), michael@0: nullptr); michael@0: if (res) { michael@0: key.Replace(key.Length() - 7, 7, NS_LITERAL_CSTRING("enabled")); michael@0: res = gconf_client_set_bool(mClient, key.get(), true, nullptr); michael@0: if (res) { michael@0: key.Replace(key.Length() - 7, 7, NS_LITERAL_CSTRING("needs_terminal")); michael@0: res = gconf_client_set_bool(mClient, key.get(), false, nullptr); michael@0: if (res) { michael@0: key.Replace(key.Length() - 14, 14, NS_LITERAL_CSTRING("command-id")); michael@0: res = gconf_client_unset(mClient, key.get(), nullptr); michael@0: } michael@0: } michael@0: } michael@0: michael@0: return res ? NS_OK : NS_ERROR_FAILURE; michael@0: }