b=611953 Add nsIGSettingsService to support GSettings r=karlt
authorChris Coulson <chrisccoulson@ubuntu.com>
Thu, 12 May 2011 20:14:55 +1200
changeset 69414 8cc9e1405f7357d196813409b3c6c11a0f4db3a5
parent 69413 73a5dcbfeeada8afcf23be006c3b8858e014c082
child 69415 1d6d08074c4113640deb1538ce6f35d9fef61839
push id19969
push userktomlinson@mozilla.com
push dateFri, 13 May 2011 03:24:56 +0000
treeherdermozilla-central@ebc9a7e1fb12 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskarlt
bugs611953
milestone6.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
b=611953 Add nsIGSettingsService to support GSettings r=karlt
toolkit/system/gnome/Makefile.in
toolkit/system/gnome/nsGSettingsService.cpp
toolkit/system/gnome/nsGSettingsService.h
toolkit/system/gnome/nsGnomeModule.cpp
xpcom/system/Makefile.in
xpcom/system/nsIGSettingsService.idl
--- a/toolkit/system/gnome/Makefile.in
+++ b/toolkit/system/gnome/Makefile.in
@@ -60,16 +60,17 @@ ifdef MOZ_ENABLE_GNOMEVFS
 CPPSRCS += \
 	nsGnomeVFSService.cpp \
 	$(NULL)
 endif
 
 ifdef MOZ_ENABLE_GIO
 CPPSRCS += \
 	nsGIOService.cpp \
+	nsGSettingsService.cpp \
 	$(NULL)
 endif
 
 ifdef MOZ_ENABLE_LIBNOTIFY
 CPPSRCS += \
 	nsAlertsService.cpp \
 	nsAlertsIconListener.cpp \
 	$(NULL)
new file mode 100644
--- /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 <chris.coulson@canonical.com>
+ *
+ * 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 <glib.h>
+#include <glib-object.h>
+
+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;
+}
new file mode 100644
--- /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 <chris.coulson@canonical.com>
+ *
+ * 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
+
--- a/toolkit/system/gnome/nsGnomeModule.cpp
+++ b/toolkit/system/gnome/nsGnomeModule.cpp
@@ -44,62 +44,67 @@
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGConfService, Init)
 #endif
 #ifdef MOZ_ENABLE_GNOMEVFS
 #include "nsGnomeVFSService.h"
 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"
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsAlertsService, Init)
 #endif
 
 #ifdef MOZ_ENABLE_GCONF
 NS_DEFINE_NAMED_CID(NS_GCONFSERVICE_CID);
 #endif
 #ifdef MOZ_ENABLE_GNOMEVFS
 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);
 #endif
 
 
 static const mozilla::Module::CIDEntry kGnomeCIDs[] = {
 #ifdef MOZ_ENABLE_GCONF
   { &kNS_GCONFSERVICE_CID, false, NULL, nsGConfServiceConstructor },
 #endif
 #ifdef MOZ_ENABLE_GNOMEVFS
   { &kNS_GNOMEVFSSERVICE_CID, false, NULL, nsGnomeVFSServiceConstructor },
 #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 },
 #endif
   { NULL }
 };
 
 static const mozilla::Module::ContractIDEntry kGnomeContracts[] = {
 #ifdef MOZ_ENABLE_GCONF
   { NS_GCONFSERVICE_CONTRACTID, &kNS_GCONFSERVICE_CID },
 #endif
 #ifdef MOZ_ENABLE_GNOMEVFS
   { NS_GNOMEVFSSERVICE_CONTRACTID, &kNS_GNOMEVFSSERVICE_CID },
 #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 },
 #endif
   { NULL }
 };
 
 static const mozilla::Module kGnomeModule = {
--- a/xpcom/system/Makefile.in
+++ b/xpcom/system/Makefile.in
@@ -47,16 +47,17 @@ XPIDL_MODULE    = xpcom_system
 
 XPIDLSRCS = \
         nsIXULAppInfo.idl \
         nsIXULRuntime.idl \
         nsIGConfService.idl \
         nsIGnomeVFSService.idl \
         nsIBlocklistService.idl \
         nsIGIOService.idl \
+        nsIGSettingsService.idl \
         nsIAccelerometer.idl \
         nsIGeolocationProvider.idl \
         nsIHapticFeedback.idl \
         $(NULL)
 
 ifdef MOZ_CRASHREPORTER
 XPIDLSRCS += nsICrashReporter.idl
 endif
new file mode 100644
--- /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 <chris.coulson@canonical.com>
+ *
+ * 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"
+%}