xpcom/threads/nsEnvironment.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/xpcom/threads/nsEnvironment.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,160 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     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 "nsEnvironment.h"
    1.10 +#include "prenv.h"
    1.11 +#include "prprf.h"
    1.12 +#include "nsBaseHashtable.h"
    1.13 +#include "nsHashKeys.h"
    1.14 +#include "nsPromiseFlatString.h"
    1.15 +#include "nsDependentString.h"
    1.16 +#include "nsNativeCharsetUtils.h"
    1.17 +
    1.18 +using namespace mozilla;
    1.19 +
    1.20 +NS_IMPL_ISUPPORTS(nsEnvironment, nsIEnvironment)
    1.21 +
    1.22 +nsresult
    1.23 +nsEnvironment::Create(nsISupports *aOuter, REFNSIID aIID,
    1.24 +                      void **aResult)
    1.25 +{
    1.26 +    nsresult rv;
    1.27 +    *aResult = nullptr;
    1.28 +
    1.29 +    if (aOuter != nullptr) {
    1.30 +        return NS_ERROR_NO_AGGREGATION;
    1.31 +    }
    1.32 +
    1.33 +    nsEnvironment* obj = new nsEnvironment();
    1.34 +    if (!obj) {
    1.35 +        return NS_ERROR_OUT_OF_MEMORY;
    1.36 +    }
    1.37 +
    1.38 +    rv = obj->QueryInterface(aIID, aResult);
    1.39 +    if (NS_FAILED(rv)) {
    1.40 +      delete obj;
    1.41 +    }
    1.42 +    return rv;
    1.43 +}
    1.44 +
    1.45 +nsEnvironment::~nsEnvironment()
    1.46 +{
    1.47 +}
    1.48 +
    1.49 +NS_IMETHODIMP
    1.50 +nsEnvironment::Exists(const nsAString& aName, bool *aOutValue)
    1.51 +{
    1.52 +    nsAutoCString nativeName;
    1.53 +    nsresult rv = NS_CopyUnicodeToNative(aName, nativeName);
    1.54 +    if (NS_WARN_IF(NS_FAILED(rv)))
    1.55 +        return rv;
    1.56 +
    1.57 +    nsAutoCString nativeVal;
    1.58 +#if defined(XP_UNIX)
    1.59 +    /* For Unix/Linux platforms we follow the Unix definition:
    1.60 +     * An environment variable exists when |getenv()| returns a non-nullptr
    1.61 +     * value. An environment variable does not exist when |getenv()| returns
    1.62 +     * nullptr.
    1.63 +     */
    1.64 +    const char *value = PR_GetEnv(nativeName.get());
    1.65 +    *aOutValue = value && *value;
    1.66 +#else
    1.67 +    /* For non-Unix/Linux platforms we have to fall back to a 
    1.68 +     * "portable" definition (which is incorrect for Unix/Linux!!!!)
    1.69 +     * which simply checks whether the string returned by |Get()| is empty
    1.70 +     * or not.
    1.71 +     */
    1.72 +    nsAutoString value;
    1.73 +    Get(aName, value);
    1.74 +    *aOutValue = !value.IsEmpty();
    1.75 +#endif /* XP_UNIX */
    1.76 +
    1.77 +    return NS_OK;
    1.78 +}
    1.79 +
    1.80 +NS_IMETHODIMP
    1.81 +nsEnvironment::Get(const nsAString& aName, nsAString& aOutValue)
    1.82 +{
    1.83 +    nsAutoCString nativeName;
    1.84 +    nsresult rv = NS_CopyUnicodeToNative(aName, nativeName);
    1.85 +    if (NS_WARN_IF(NS_FAILED(rv)))
    1.86 +        return rv;
    1.87 +
    1.88 +    nsAutoCString nativeVal;
    1.89 +    const char *value = PR_GetEnv(nativeName.get());
    1.90 +    if (value && *value) {
    1.91 +        rv = NS_CopyNativeToUnicode(nsDependentCString(value), aOutValue);
    1.92 +    } else {
    1.93 +        aOutValue.Truncate();
    1.94 +        rv = NS_OK;
    1.95 +    }
    1.96 +
    1.97 +    return rv;
    1.98 +}
    1.99 +
   1.100 +/* Environment strings must have static duration; We're gonna leak all of this
   1.101 + * at shutdown: this is by design, caused how Unix/Linux implement environment
   1.102 + * vars. 
   1.103 + */
   1.104 +
   1.105 +typedef nsBaseHashtableET<nsCharPtrHashKey,char*> EnvEntryType;
   1.106 +typedef nsTHashtable<EnvEntryType> EnvHashType;
   1.107 +
   1.108 +static EnvHashType *gEnvHash = nullptr;
   1.109 +
   1.110 +static bool
   1.111 +EnsureEnvHash()
   1.112 +{
   1.113 +    if (gEnvHash)
   1.114 +        return true;
   1.115 +
   1.116 +    gEnvHash = new EnvHashType;
   1.117 +    if (!gEnvHash)
   1.118 +        return false;
   1.119 +
   1.120 +    return true;
   1.121 +}
   1.122 +
   1.123 +NS_IMETHODIMP
   1.124 +nsEnvironment::Set(const nsAString& aName, const nsAString& aValue)
   1.125 +{
   1.126 +    nsAutoCString nativeName;
   1.127 +    nsAutoCString nativeVal;
   1.128 +
   1.129 +    nsresult rv = NS_CopyUnicodeToNative(aName, nativeName);
   1.130 +    if (NS_WARN_IF(NS_FAILED(rv)))
   1.131 +        return rv;
   1.132 +
   1.133 +    rv = NS_CopyUnicodeToNative(aValue, nativeVal);
   1.134 +    if (NS_WARN_IF(NS_FAILED(rv)))
   1.135 +        return rv;
   1.136 +
   1.137 +    MutexAutoLock lock(mLock);
   1.138 +
   1.139 +    if (!EnsureEnvHash()){
   1.140 +        return NS_ERROR_UNEXPECTED;
   1.141 +    }
   1.142 +
   1.143 +    EnvEntryType* entry = gEnvHash->PutEntry(nativeName.get());
   1.144 +    if (!entry) {
   1.145 +        return NS_ERROR_OUT_OF_MEMORY;
   1.146 +    }
   1.147 +    
   1.148 +    char* newData = PR_smprintf("%s=%s",
   1.149 +                                nativeName.get(),
   1.150 +                                nativeVal.get());
   1.151 +    if (!newData) {
   1.152 +        return NS_ERROR_OUT_OF_MEMORY;
   1.153 +    } 
   1.154 +    
   1.155 +    PR_SetEnv(newData);
   1.156 +    if (entry->mData) {
   1.157 +        PR_smprintf_free(entry->mData);
   1.158 +    }
   1.159 +    entry->mData = newData;
   1.160 +    return NS_OK;
   1.161 +}
   1.162 +
   1.163 +

mercurial