From 640ca82a0202d5b03f9f565f6409e646e38d465b Mon Sep 17 00:00:00 2001 From: Chris Coulson Date: Thu, 12 May 2011 20:14:55 +1200 Subject: [PATCH] b=611953 Add nsIGSettingsService to support GSettings r=karlt --HG-- extra : rebase_source : 01cee722e375c8acc82cb6169a096d73026030aa --- toolkit/system/gnome/Makefile.in | 1 + toolkit/system/gnome/nsGSettingsService.cpp | 325 ++++++++++++++++++++ toolkit/system/gnome/nsGSettingsService.h | 60 ++++ toolkit/system/gnome/nsGnomeModule.cpp | 5 + xpcom/system/Makefile.in | 1 + xpcom/system/nsIGSettingsService.idl | 61 ++++ 6 files changed, 453 insertions(+) create mode 100644 toolkit/system/gnome/nsGSettingsService.cpp create mode 100644 toolkit/system/gnome/nsGSettingsService.h create mode 100644 xpcom/system/nsIGSettingsService.idl diff --git a/toolkit/system/gnome/Makefile.in b/toolkit/system/gnome/Makefile.in index 3dc5c126351..609408ba798 100644 --- a/toolkit/system/gnome/Makefile.in +++ b/toolkit/system/gnome/Makefile.in @@ -65,6 +65,7 @@ endif ifdef MOZ_ENABLE_GIO CPPSRCS += \ nsGIOService.cpp \ + nsGSettingsService.cpp \ $(NULL) endif diff --git a/toolkit/system/gnome/nsGSettingsService.cpp b/toolkit/system/gnome/nsGSettingsService.cpp new file mode 100644 index 00000000000..d7b143ae0cf --- /dev/null +++ b/toolkit/system/gnome/nsGSettingsService.cpp @@ -0,0 +1,325 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Mozilla GNOME integration code. + * + * The Initial Developer of the Original Code is + * Canonical Ltd. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Coulson + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsGSettingsService.h" +#include "nsStringAPI.h" +#include "nsCOMPtr.h" +#include "nsMemory.h" +#include "prlink.h" +#include "nsComponentManagerUtils.h" + +#include +#include + +typedef struct _GSettings GSettings; +typedef struct _GVariantType GVariantType; +typedef struct _GVariant GVariant; + +#ifndef G_VARIANT_TYPE_INT32 +# define G_VARIANT_TYPE_INT32 ((const GVariantType *) "i") +# define G_VARIANT_TYPE_BOOLEAN ((const GVariantType *) "b") +# define G_VARIANT_TYPE_STRING ((const GVariantType *) "s") +# define G_VARIANT_TYPE_OBJECT_PATH ((const GVariantType *) "o") +# define G_VARIANT_TYPE_SIGNATURE ((const GVariantType *) "g") +#endif + +#define GSETTINGS_FUNCTIONS \ + FUNC(g_settings_new, GSettings *, (const char* schema)) \ + FUNC(g_settings_list_schemas, const char * const *, (void)) \ + FUNC(g_settings_list_keys, char **, (GSettings* settings)) \ + FUNC(g_settings_get_value, GVariant *, (GSettings* settings, const char* key)) \ + FUNC(g_settings_set_value, gboolean, (GSettings* settings, const char* key, GVariant* value)) \ + FUNC(g_settings_range_check, gboolean, (GSettings* settings, const char* key, GVariant* value)) \ + FUNC(g_variant_get_int32, gint32, (GVariant* variant)) \ + FUNC(g_variant_get_boolean, gboolean, (GVariant* variant)) \ + FUNC(g_variant_get_string, const char *, (GVariant* value, gsize* length)) \ + FUNC(g_variant_is_of_type, gboolean, (GVariant* value, const GVariantType* type)) \ + FUNC(g_variant_new_int32, GVariant *, (gint32 value)) \ + FUNC(g_variant_new_boolean, GVariant *, (gboolean value)) \ + FUNC(g_variant_new_string, GVariant *, (const char* string)) \ + FUNC(g_variant_unref, void, (GVariant* value)) + +#define FUNC(name, type, params) \ + typedef type (*_##name##_fn) params; \ + static _##name##_fn _##name; + +GSETTINGS_FUNCTIONS + +#undef FUNC + +#define g_settings_new _g_settings_new +#define g_settings_list_schemas _g_settings_list_schemas +#define g_settings_list_keys _g_settings_list_keys +#define g_settings_get_value _g_settings_get_value +#define g_settings_set_value _g_settings_set_value +#define g_settings_range_check _g_settings_range_check +#define g_variant_get_int32 _g_variant_get_int32 +#define g_variant_get_boolean _g_variant_get_boolean +#define g_variant_get_string _g_variant_get_string +#define g_variant_is_of_type _g_variant_is_of_type +#define g_variant_new_int32 _g_variant_new_int32 +#define g_variant_new_boolean _g_variant_new_boolean +#define g_variant_new_string _g_variant_new_string +#define g_variant_unref _g_variant_unref + +static PRLibrary *gioLib = nsnull; + +class nsGSettingsCollection : public nsIGSettingsCollection +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIGSETTINGSCOLLECTION + + nsGSettingsCollection(GSettings* aSettings) : mSettings(aSettings), + mKeys(NULL) {}; + ~nsGSettingsCollection(); + +private: + PRBool KeyExists(const nsACString& aKey); + PRBool SetValue(const nsACString& aKey, + GVariant *aValue); + + GSettings *mSettings; + char **mKeys; +}; + +nsGSettingsCollection::~nsGSettingsCollection() +{ + g_strfreev(mKeys); + g_object_unref(mSettings); +} + +PRBool +nsGSettingsCollection::KeyExists(const nsACString& aKey) +{ + if (!mKeys) + mKeys = g_settings_list_keys(mSettings); + + for (PRUint32 i = 0; mKeys[i] != NULL; i++) { + if (aKey.Equals(mKeys[i])) + return PR_TRUE; + } + + return PR_FALSE; +} + +PRBool +nsGSettingsCollection::SetValue(const nsACString& aKey, + GVariant *aValue) +{ + if (!KeyExists(aKey) || + !g_settings_range_check(mSettings, + PromiseFlatCString(aKey).get(), + aValue)) { + g_variant_unref(aValue); + return PR_FALSE; + } + + return g_settings_set_value(mSettings, + PromiseFlatCString(aKey).get(), + aValue); +} + +NS_IMPL_ISUPPORTS1(nsGSettingsCollection, nsIGSettingsCollection) + +NS_IMETHODIMP +nsGSettingsCollection::SetString(const nsACString& aKey, + const nsACString& aValue) +{ + GVariant *value = g_variant_new_string(PromiseFlatCString(aValue).get()); + if (!value) + return NS_ERROR_OUT_OF_MEMORY; + + PRBool res = SetValue(aKey, value); + + return res ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsGSettingsCollection::SetBoolean(const nsACString& aKey, + PRBool aValue) +{ + GVariant *value = g_variant_new_boolean(aValue); + if (!value) + return NS_ERROR_OUT_OF_MEMORY; + + PRBool res = SetValue(aKey, value); + + return res ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsGSettingsCollection::SetInt(const nsACString& aKey, + PRInt32 aValue) +{ + GVariant *value = g_variant_new_int32(aValue); + if (!value) + return NS_ERROR_OUT_OF_MEMORY; + + PRBool res = SetValue(aKey, value); + + return res ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsGSettingsCollection::GetString(const nsACString& aKey, + nsACString& aResult) +{ + if (!KeyExists(aKey)) + return NS_ERROR_INVALID_ARG; + + GVariant *value = g_settings_get_value(mSettings, + PromiseFlatCString(aKey).get()); + if (!g_variant_is_of_type(value, G_VARIANT_TYPE_STRING) && + !g_variant_is_of_type(value, G_VARIANT_TYPE_OBJECT_PATH) && + !g_variant_is_of_type(value, G_VARIANT_TYPE_SIGNATURE)) { + g_variant_unref(value); + return NS_ERROR_FAILURE; + } + + aResult.Assign(g_variant_get_string(value, NULL)); + g_variant_unref(value); + + return NS_OK; +} + +NS_IMETHODIMP +nsGSettingsCollection::GetBoolean(const nsACString& aKey, + PRBool* aResult) +{ + NS_ENSURE_ARG_POINTER(aResult); + + if (!KeyExists(aKey)) + return NS_ERROR_INVALID_ARG; + + GVariant *value = g_settings_get_value(mSettings, + PromiseFlatCString(aKey).get()); + if (!g_variant_is_of_type(value, G_VARIANT_TYPE_BOOLEAN)) { + g_variant_unref(value); + return NS_ERROR_FAILURE; + } + + gboolean res = g_variant_get_boolean(value); + *aResult = res ? PR_TRUE : PR_FALSE; + g_variant_unref(value); + + return NS_OK; +} + +NS_IMETHODIMP +nsGSettingsCollection::GetInt(const nsACString& aKey, + PRInt32* aResult) +{ + NS_ENSURE_ARG_POINTER(aResult); + + if (!KeyExists(aKey)) + return NS_ERROR_INVALID_ARG; + + GVariant *value = g_settings_get_value(mSettings, + PromiseFlatCString(aKey).get()); + if (!g_variant_is_of_type(value, G_VARIANT_TYPE_INT32)) { + g_variant_unref(value); + return NS_ERROR_FAILURE; + } + + *aResult = g_variant_get_int32(value); + g_variant_unref(value); + + return NS_OK; +} + +nsresult +nsGSettingsService::Init() +{ +#define FUNC(name, type, params) { #name, (nsGSettingsFunc *)&_##name }, + typedef void (*nsGSettingsFunc)(); + static const struct nsGSettingsDynamicFunction { + const char *functionName; + nsGSettingsFunc *function; + } kGSettingsSymbols[] = { + GSETTINGS_FUNCTIONS + }; +#undef FUNC + + if (!gioLib) { + gioLib = PR_LoadLibrary("libgio-2.0.so.0"); + if (!gioLib) + return NS_ERROR_FAILURE; + } + + for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(kGSettingsSymbols); i++) { + *kGSettingsSymbols[i].function = + PR_FindFunctionSymbol(gioLib, kGSettingsSymbols[i].functionName); + if (!*kGSettingsSymbols[i].function) { + PR_UnloadLibrary(gioLib); + return NS_ERROR_FAILURE; + } + } + + return NS_OK; +} + +NS_IMPL_ISUPPORTS1(nsGSettingsService, nsIGSettingsService) + +nsGSettingsService::~nsGSettingsService() +{ + if (gioLib) { + PR_UnloadLibrary(gioLib); + gioLib = nsnull; + } +} + +NS_IMETHODIMP +nsGSettingsService::GetCollectionForSchema(const nsACString& schema, + nsIGSettingsCollection** collection) +{ + NS_ENSURE_ARG_POINTER(collection); + + const char * const *schemas = g_settings_list_schemas(); + + for (PRUint32 i = 0; schemas[i] != NULL; i++) { + if (schema.Equals(schemas[i])) { + GSettings *settings = g_settings_new(PromiseFlatCString(schema).get()); + nsGSettingsCollection *mozGSettings = new nsGSettingsCollection(settings); + NS_ADDREF(*collection = mozGSettings); + return NS_OK; + } + } + + return NS_ERROR_FAILURE; +} diff --git a/toolkit/system/gnome/nsGSettingsService.h b/toolkit/system/gnome/nsGSettingsService.h new file mode 100644 index 00000000000..59f07c257fc --- /dev/null +++ b/toolkit/system/gnome/nsGSettingsService.h @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Mozilla GNOME integration code. + * + * The Initial Developer of the Original Code is + * Canonical Ltd. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Coulson + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsGSettingsService_h_ +#define nsGSettingsService_h_ + +#include "nsIGSettingsService.h" + +#define NS_GSETTINGSSERVICE_CID \ +{0xbfd4a9d8, 0xd886, 0x4161, {0x81, 0xef, 0x88, 0x68, 0xda, 0x11, 0x41, 0x70}} + +class nsGSettingsService : public nsIGSettingsService +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIGSETTINGSSERVICE + + NS_HIDDEN_(nsresult) Init(); + +private: + ~nsGSettingsService(); +}; + +#endif + diff --git a/toolkit/system/gnome/nsGnomeModule.cpp b/toolkit/system/gnome/nsGnomeModule.cpp index b5d2b66249a..368954e687c 100644 --- a/toolkit/system/gnome/nsGnomeModule.cpp +++ b/toolkit/system/gnome/nsGnomeModule.cpp @@ -49,7 +49,9 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGnomeVFSService, Init) #endif #ifdef MOZ_ENABLE_GIO #include "nsGIOService.h" +#include "nsGSettingsService.h" NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGIOService, Init) +NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGSettingsService, Init) #endif #ifdef MOZ_ENABLE_LIBNOTIFY #include "nsAlertsService.h" @@ -64,6 +66,7 @@ NS_DEFINE_NAMED_CID(NS_GNOMEVFSSERVICE_CID); #endif #ifdef MOZ_ENABLE_GIO NS_DEFINE_NAMED_CID(NS_GIOSERVICE_CID); +NS_DEFINE_NAMED_CID(NS_GSETTINGSSERVICE_CID); #endif #ifdef MOZ_ENABLE_LIBNOTIFY NS_DEFINE_NAMED_CID(NS_SYSTEMALERTSSERVICE_CID); @@ -79,6 +82,7 @@ static const mozilla::Module::CIDEntry kGnomeCIDs[] = { #endif #ifdef MOZ_ENABLE_GIO { &kNS_GIOSERVICE_CID, false, NULL, nsGIOServiceConstructor }, + { &kNS_GSETTINGSSERVICE_CID, false, NULL, nsGSettingsServiceConstructor }, #endif #ifdef MOZ_ENABLE_LIBNOTIFY { &kNS_SYSTEMALERTSSERVICE_CID, false, NULL, nsAlertsServiceConstructor }, @@ -95,6 +99,7 @@ static const mozilla::Module::ContractIDEntry kGnomeContracts[] = { #endif #ifdef MOZ_ENABLE_GIO { NS_GIOSERVICE_CONTRACTID, &kNS_GIOSERVICE_CID }, + { NS_GSETTINGSSERVICE_CONTRACTID, &kNS_GSETTINGSSERVICE_CID }, #endif #ifdef MOZ_ENABLE_LIBNOTIFY { NS_SYSTEMALERTSERVICE_CONTRACTID, &kNS_SYSTEMALERTSSERVICE_CID }, diff --git a/xpcom/system/Makefile.in b/xpcom/system/Makefile.in index a3655fb333e..ddffb0697d9 100644 --- a/xpcom/system/Makefile.in +++ b/xpcom/system/Makefile.in @@ -52,6 +52,7 @@ XPIDLSRCS = \ nsIGnomeVFSService.idl \ nsIBlocklistService.idl \ nsIGIOService.idl \ + nsIGSettingsService.idl \ nsIAccelerometer.idl \ nsIGeolocationProvider.idl \ nsIHapticFeedback.idl \ diff --git a/xpcom/system/nsIGSettingsService.idl b/xpcom/system/nsIGSettingsService.idl new file mode 100644 index 00000000000..0249ef82c37 --- /dev/null +++ b/xpcom/system/nsIGSettingsService.idl @@ -0,0 +1,61 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Mozilla GNOME integration code. + * + * The Initial Developer of the Original Code is + * Canonical Ltd. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Coulson + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" +#include "nsIArray.idl" + +[scriptable, uuid(09637d3c-3c07-40b4-aff9-1d2a0f046f3c)] +interface nsIGSettingsCollection : nsISupports +{ + void setString(in AUTF8String key, in AUTF8String value); + void setBoolean(in AUTF8String key, in boolean value); + void setInt(in AUTF8String key, in long value); + AUTF8String getString(in AUTF8String key); + boolean getBoolean(in AUTF8String key); + long getInt(in AUTF8String key); +}; + +[scriptable, uuid(849c088b-57d1-4f24-b7b2-3dc4acb04c0a)] +interface nsIGSettingsService : nsISupports +{ + nsIGSettingsCollection getCollectionForSchema(in AUTF8String schema); +}; + +%{C++ +#define NS_GSETTINGSSERVICE_CONTRACTID "@mozilla.org/gsettings-service;1" +%}