LCOV - code coverage report
Current view: top level - toolkit/system/gnome - nsGSettingsService.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 133 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 20 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
       8             : #include "nsGSettingsService.h"
       9             : #include "nsString.h"
      10             : #include "nsCOMPtr.h"
      11             : #include "nsMemory.h"
      12             : #include "prlink.h"
      13             : #include "nsComponentManagerUtils.h"
      14             : #include "nsIMutableArray.h"
      15             : #include "nsISupportsPrimitives.h"
      16             : 
      17             : #include <glib.h>
      18             : #include <glib-object.h>
      19             : 
      20             : using namespace mozilla;
      21             : 
      22             : typedef struct _GSettings GSettings;
      23             : typedef struct _GVariantType GVariantType;
      24             : typedef struct _GVariant GVariant;
      25             : 
      26             : #ifndef G_VARIANT_TYPE_INT32
      27             : # define G_VARIANT_TYPE_INT32        ((const GVariantType *) "i")
      28             : # define G_VARIANT_TYPE_BOOLEAN      ((const GVariantType *) "b")
      29             : # define G_VARIANT_TYPE_STRING       ((const GVariantType *) "s")
      30             : # define G_VARIANT_TYPE_OBJECT_PATH  ((const GVariantType *) "o")
      31             : # define G_VARIANT_TYPE_SIGNATURE    ((const GVariantType *) "g")
      32             : #endif
      33             : #ifndef G_VARIANT_TYPE_STRING_ARRAY
      34             : # define G_VARIANT_TYPE_STRING_ARRAY ((const GVariantType *) "as")
      35             : #endif
      36             : 
      37             : #define GSETTINGS_FUNCTIONS \
      38             :   FUNC(g_settings_new, GSettings *, (const char* schema)) \
      39             :   FUNC(g_settings_list_schemas, const char * const *, (void)) \
      40             :   FUNC(g_settings_list_keys, char **, (GSettings* settings)) \
      41             :   FUNC(g_settings_get_value, GVariant *, (GSettings* settings, const char* key)) \
      42             :   FUNC(g_settings_set_value, gboolean, (GSettings* settings, const char* key, GVariant* value)) \
      43             :   FUNC(g_settings_range_check, gboolean, (GSettings* settings, const char* key, GVariant* value)) \
      44             :   FUNC(g_variant_get_int32, gint32, (GVariant* variant)) \
      45             :   FUNC(g_variant_get_boolean, gboolean, (GVariant* variant)) \
      46             :   FUNC(g_variant_get_string, const char *, (GVariant* value, gsize* length)) \
      47             :   FUNC(g_variant_get_strv, const char **, (GVariant* value, gsize* length)) \
      48             :   FUNC(g_variant_is_of_type, gboolean, (GVariant* value, const GVariantType* type)) \
      49             :   FUNC(g_variant_new_int32, GVariant *, (gint32 value)) \
      50             :   FUNC(g_variant_new_boolean, GVariant *, (gboolean value)) \
      51             :   FUNC(g_variant_new_string, GVariant *, (const char* string)) \
      52             :   FUNC(g_variant_unref, void, (GVariant* value))
      53             : 
      54             : #define FUNC(name, type, params) \
      55             :   typedef type (*_##name##_fn) params; \
      56             :   static _##name##_fn _##name;
      57             : 
      58             : GSETTINGS_FUNCTIONS
      59             : 
      60             : #undef FUNC
      61             : 
      62             : #define g_settings_new _g_settings_new
      63             : #define g_settings_list_schemas _g_settings_list_schemas
      64             : #define g_settings_list_keys _g_settings_list_keys
      65             : #define g_settings_get_value _g_settings_get_value
      66             : #define g_settings_set_value _g_settings_set_value
      67             : #define g_settings_range_check _g_settings_range_check
      68             : #define g_variant_get_int32 _g_variant_get_int32
      69             : #define g_variant_get_boolean _g_variant_get_boolean
      70             : #define g_variant_get_string _g_variant_get_string
      71             : #define g_variant_get_strv _g_variant_get_strv
      72             : #define g_variant_is_of_type _g_variant_is_of_type
      73             : #define g_variant_new_int32 _g_variant_new_int32
      74             : #define g_variant_new_boolean _g_variant_new_boolean
      75             : #define g_variant_new_string _g_variant_new_string
      76             : #define g_variant_unref _g_variant_unref
      77             : 
      78             : static PRLibrary *gioLib = nullptr;
      79             : 
      80             : class nsGSettingsCollection final : public nsIGSettingsCollection
      81             : {
      82             : public:
      83             :   NS_DECL_ISUPPORTS
      84             :   NS_DECL_NSIGSETTINGSCOLLECTION
      85             : 
      86           0 :   explicit nsGSettingsCollection(GSettings* aSettings) : mSettings(aSettings),
      87           0 :                                                          mKeys(nullptr) {}
      88             : private:
      89             :   ~nsGSettingsCollection();
      90             : 
      91             :   bool KeyExists(const nsACString& aKey);
      92             :   bool SetValue(const nsACString& aKey,
      93             :                   GVariant *aValue);
      94             : 
      95             :   GSettings *mSettings;
      96             :   char **mKeys;
      97             : };
      98             : 
      99           0 : nsGSettingsCollection::~nsGSettingsCollection()
     100             : {
     101           0 :   g_strfreev(mKeys);
     102           0 :   g_object_unref(mSettings);
     103           0 : }
     104             : 
     105             : bool
     106           0 : nsGSettingsCollection::KeyExists(const nsACString& aKey)
     107             : {
     108           0 :   if (!mKeys)
     109           0 :     mKeys = g_settings_list_keys(mSettings);
     110             : 
     111           0 :   for (uint32_t i = 0; mKeys[i] != nullptr; i++) {
     112           0 :     if (aKey.Equals(mKeys[i]))
     113           0 :       return true;
     114             :   }
     115             : 
     116           0 :   return false;
     117             : }
     118             : 
     119             : bool
     120           0 : nsGSettingsCollection::SetValue(const nsACString& aKey,
     121             :                                 GVariant *aValue)
     122             : {
     123           0 :   if (!KeyExists(aKey) ||
     124           0 :       !g_settings_range_check(mSettings,
     125           0 :                               PromiseFlatCString(aKey).get(),
     126             :                               aValue)) {
     127           0 :     g_variant_unref(aValue);
     128           0 :     return false;
     129             :   }
     130             : 
     131           0 :   return g_settings_set_value(mSettings,
     132           0 :                               PromiseFlatCString(aKey).get(),
     133           0 :                               aValue);
     134             : }
     135             : 
     136           0 : NS_IMPL_ISUPPORTS(nsGSettingsCollection, nsIGSettingsCollection)
     137             : 
     138             : NS_IMETHODIMP
     139           0 : nsGSettingsCollection::SetString(const nsACString& aKey,
     140             :                                  const nsACString& aValue)
     141             : {
     142           0 :   GVariant *value = g_variant_new_string(PromiseFlatCString(aValue).get());
     143           0 :   if (!value)
     144           0 :     return NS_ERROR_OUT_OF_MEMORY;
     145             : 
     146           0 :   bool res = SetValue(aKey, value);
     147             : 
     148           0 :   return res ? NS_OK : NS_ERROR_FAILURE;
     149             : }
     150             : 
     151             : NS_IMETHODIMP
     152           0 : nsGSettingsCollection::SetBoolean(const nsACString& aKey,
     153             :                                   bool aValue)
     154             : {
     155           0 :   GVariant *value = g_variant_new_boolean(aValue);
     156           0 :   if (!value)
     157           0 :     return NS_ERROR_OUT_OF_MEMORY;
     158             : 
     159           0 :   bool res = SetValue(aKey, value);
     160             : 
     161           0 :   return res ? NS_OK : NS_ERROR_FAILURE;
     162             : }
     163             : 
     164             : NS_IMETHODIMP
     165           0 : nsGSettingsCollection::SetInt(const nsACString& aKey,
     166             :                               int32_t aValue)
     167             : {
     168           0 :   GVariant *value = g_variant_new_int32(aValue);
     169           0 :   if (!value)
     170           0 :     return NS_ERROR_OUT_OF_MEMORY;
     171             : 
     172           0 :   bool res = SetValue(aKey, value);
     173             : 
     174           0 :   return res ? NS_OK : NS_ERROR_FAILURE;
     175             : }
     176             : 
     177             : NS_IMETHODIMP
     178           0 : nsGSettingsCollection::GetString(const nsACString& aKey,
     179             :                                  nsACString& aResult)
     180             : {
     181           0 :   if (!KeyExists(aKey))
     182           0 :     return NS_ERROR_INVALID_ARG;
     183             : 
     184           0 :   GVariant *value = g_settings_get_value(mSettings,
     185           0 :                                          PromiseFlatCString(aKey).get());
     186           0 :   if (!g_variant_is_of_type(value, G_VARIANT_TYPE_STRING) &&
     187           0 :       !g_variant_is_of_type(value, G_VARIANT_TYPE_OBJECT_PATH) &&
     188           0 :       !g_variant_is_of_type(value, G_VARIANT_TYPE_SIGNATURE)) {
     189           0 :     g_variant_unref(value);
     190           0 :     return NS_ERROR_FAILURE;
     191             :   }
     192             : 
     193           0 :   aResult.Assign(g_variant_get_string(value, nullptr));
     194           0 :   g_variant_unref(value);
     195             : 
     196           0 :   return NS_OK;
     197             : }
     198             : 
     199             : NS_IMETHODIMP
     200           0 : nsGSettingsCollection::GetBoolean(const nsACString& aKey,
     201             :                                   bool* aResult)
     202             : {
     203           0 :   NS_ENSURE_ARG_POINTER(aResult);
     204             : 
     205           0 :   if (!KeyExists(aKey))
     206           0 :     return NS_ERROR_INVALID_ARG;
     207             : 
     208           0 :   GVariant *value = g_settings_get_value(mSettings,
     209           0 :                                          PromiseFlatCString(aKey).get());
     210           0 :   if (!g_variant_is_of_type(value, G_VARIANT_TYPE_BOOLEAN)) {
     211           0 :     g_variant_unref(value);
     212           0 :     return NS_ERROR_FAILURE;
     213             :   }
     214             : 
     215           0 :   gboolean res = g_variant_get_boolean(value);
     216           0 :   *aResult = res ? true : false;
     217           0 :   g_variant_unref(value);
     218             : 
     219           0 :   return NS_OK;
     220             : }
     221             : 
     222             : NS_IMETHODIMP
     223           0 : nsGSettingsCollection::GetInt(const nsACString& aKey,
     224             :                               int32_t* aResult)
     225             : {
     226           0 :   NS_ENSURE_ARG_POINTER(aResult);
     227             : 
     228           0 :   if (!KeyExists(aKey))
     229           0 :     return NS_ERROR_INVALID_ARG;
     230             : 
     231           0 :   GVariant *value = g_settings_get_value(mSettings,
     232           0 :                                          PromiseFlatCString(aKey).get());
     233           0 :   if (!g_variant_is_of_type(value, G_VARIANT_TYPE_INT32)) {
     234           0 :     g_variant_unref(value);
     235           0 :     return NS_ERROR_FAILURE;
     236             :   }
     237             : 
     238           0 :   *aResult = g_variant_get_int32(value);
     239           0 :   g_variant_unref(value);
     240             : 
     241           0 :   return NS_OK;
     242             : }
     243             : 
     244             : // These types are local to nsGSettingsService::Init, but ISO C++98 doesn't
     245             : // allow a template (ArrayLength) to be instantiated based on a local type.
     246             : // Boo-urns!
     247             : typedef void (*nsGSettingsFunc)();
     248             : struct nsGSettingsDynamicFunction {
     249             :   const char *functionName;
     250             :   nsGSettingsFunc *function;
     251             : };
     252             : 
     253             : NS_IMETHODIMP
     254           0 : nsGSettingsCollection::GetStringList(const nsACString& aKey, nsIArray** aResult)
     255             : {
     256           0 :   if (!KeyExists(aKey))
     257           0 :     return NS_ERROR_INVALID_ARG;
     258             : 
     259           0 :   nsCOMPtr<nsIMutableArray> items(do_CreateInstance(NS_ARRAY_CONTRACTID));
     260           0 :   if (!items) {
     261           0 :     return NS_ERROR_OUT_OF_MEMORY;
     262             :   }
     263             : 
     264           0 :   GVariant *value = g_settings_get_value(mSettings,
     265           0 :                                          PromiseFlatCString(aKey).get());
     266             : 
     267           0 :   if (!g_variant_is_of_type(value, G_VARIANT_TYPE_STRING_ARRAY)) {
     268           0 :     g_variant_unref(value);
     269           0 :     return NS_ERROR_FAILURE;
     270             :   }
     271             : 
     272           0 :   const gchar ** gs_strings = g_variant_get_strv(value, nullptr);
     273           0 :   if (!gs_strings) {
     274             :     // empty array
     275           0 :     items.forget(aResult);
     276           0 :     g_variant_unref(value);
     277           0 :     return NS_OK;
     278             :   }
     279             : 
     280           0 :   const gchar** p_gs_strings = gs_strings;
     281           0 :   while (*p_gs_strings != nullptr)
     282             :   {
     283           0 :     nsCOMPtr<nsISupportsCString> obj(do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID));
     284           0 :     if (obj) {
     285           0 :       obj->SetData(nsDependentCString(*p_gs_strings));
     286           0 :       items->AppendElement(obj, false);
     287             :     }
     288           0 :     p_gs_strings++;
     289             :   }
     290           0 :   g_free(gs_strings);
     291           0 :   items.forget(aResult);
     292           0 :   g_variant_unref(value);
     293           0 :   return NS_OK;
     294             : }
     295             : 
     296             : nsresult
     297           0 : nsGSettingsService::Init()
     298             : {
     299             : #define FUNC(name, type, params) { #name, (nsGSettingsFunc *)&_##name },
     300             :   static const nsGSettingsDynamicFunction kGSettingsSymbols[] = {
     301             :     GSETTINGS_FUNCTIONS
     302             :   };
     303             : #undef FUNC
     304             : 
     305           0 :   if (!gioLib) {
     306           0 :     gioLib = PR_LoadLibrary("libgio-2.0.so.0");
     307           0 :     if (!gioLib)
     308           0 :       return NS_ERROR_FAILURE;
     309             :   }
     310             : 
     311           0 :   for (auto GSettingsSymbol : kGSettingsSymbols) {
     312           0 :     *GSettingsSymbol.function =
     313           0 :       PR_FindFunctionSymbol(gioLib, GSettingsSymbol.functionName);
     314           0 :     if (!*GSettingsSymbol.function) {
     315           0 :       return NS_ERROR_FAILURE;
     316             :     }
     317             :   }
     318             : 
     319           0 :   return NS_OK;
     320             : }
     321             : 
     322           0 : NS_IMPL_ISUPPORTS(nsGSettingsService, nsIGSettingsService)
     323             : 
     324           0 : nsGSettingsService::~nsGSettingsService()
     325             : {
     326           0 :   if (gioLib) {
     327           0 :     PR_UnloadLibrary(gioLib);
     328           0 :     gioLib = nullptr;
     329             :   }
     330           0 : }
     331             : 
     332             : NS_IMETHODIMP
     333           0 : nsGSettingsService::GetCollectionForSchema(const nsACString& schema,
     334             :                                            nsIGSettingsCollection** collection)
     335             : {
     336           0 :   NS_ENSURE_ARG_POINTER(collection);
     337             : 
     338           0 :   const char * const *schemas = g_settings_list_schemas();
     339             : 
     340           0 :   for (uint32_t i = 0; schemas[i] != nullptr; i++) {
     341           0 :     if (schema.Equals(schemas[i])) {
     342           0 :       GSettings *settings = g_settings_new(PromiseFlatCString(schema).get());
     343           0 :       nsGSettingsCollection *mozGSettings = new nsGSettingsCollection(settings);
     344           0 :       NS_ADDREF(*collection = mozGSettings);
     345           0 :       return NS_OK;
     346             :     }
     347             :   }
     348             : 
     349           0 :   return NS_ERROR_FAILURE;
     350             : }

Generated by: LCOV version 1.13