From 8697a8f8d8a9c8bb737628a5832b0263a7c9e2f4 Mon Sep 17 00:00:00 2001 From: "neil%parkwaycc.co.uk" Date: Fri, 23 Jan 2004 10:23:12 +0000 Subject: [PATCH] Bug 227500 Provide scriptable environment access p=bsmedberg,gisburn r/sr=dougt --- extensions/pref/autoconfig/src/prefcalls.js | 6 +- xpcom/build/nsXPComInit.cpp | 4 + xpcom/threads/Makefile.in | 2 + xpcom/threads/nsEnvironment.cpp | 202 ++++++++++++++++++++ xpcom/threads/nsEnvironment.h | 67 +++++++ xpcom/threads/nsIEnvironment.idl | 89 +++++++++ xpcom/threads/nsIProcess.idl | 11 -- xpcom/threads/nsProcessCommon.cpp | 11 -- xpcom/threads/nsProcessMac.cpp | 11 -- 9 files changed, 367 insertions(+), 36 deletions(-) create mode 100644 xpcom/threads/nsEnvironment.cpp create mode 100644 xpcom/threads/nsEnvironment.h create mode 100644 xpcom/threads/nsIEnvironment.idl diff --git a/extensions/pref/autoconfig/src/prefcalls.js b/extensions/pref/autoconfig/src/prefcalls.js index cd85182fb2c..9940ffccdb8 100644 --- a/extensions/pref/autoconfig/src/prefcalls.js +++ b/extensions/pref/autoconfig/src/prefcalls.js @@ -208,10 +208,10 @@ function displayError(funcname, message) { } function getenv(name) { - try { - var currentProcess=Components.classes["@mozilla.org/process/util;1"].createInstance(Components.interfaces.nsIProcess); - return currentProcess.getEnvironment(name); + var environment = Components.classes["@mozilla.org/process/environment;1"]. + getService(Components.interfaces.nsIEnvironment); + return environment.get(name); } catch(e) { displayError("getEnvironment", e); diff --git a/xpcom/build/nsXPComInit.cpp b/xpcom/build/nsXPComInit.cpp index 26b5da96078..4363960ea08 100644 --- a/xpcom/build/nsXPComInit.cpp +++ b/xpcom/build/nsXPComInit.cpp @@ -79,6 +79,7 @@ #include "nsThread.h" #include "nsProcess.h" +#include "nsEnvironment.h" #include "nsEmptyEnumerator.h" @@ -129,6 +130,8 @@ static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); NS_GENERIC_FACTORY_CONSTRUCTOR(nsProcess) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsEventQueueServiceImpl, Init) +#define NS_ENVIRONMENT_CLASSNAME "Environment Service" + #include "nsXPCOM.h" // ds/nsISupportsPrimitives #define NS_SUPPORTS_ID_CLASSNAME "Supports ID" @@ -341,6 +344,7 @@ static const nsModuleComponentInfo components[] = { #define NS_DIRECTORY_SERVICE_CLASSNAME "nsIFile Directory Service" COMPONENT(DIRECTORY_SERVICE, nsDirectoryService::Create), COMPONENT(PROCESS, nsProcessConstructor), + COMPONENT(ENVIRONMENT, nsEnvironment::Create), COMPONENT(STRINGINPUTSTREAM, nsStringInputStreamConstructor), COMPONENT(MULTIPLEXINPUTSTREAM, nsMultiplexInputStreamConstructor), diff --git a/xpcom/threads/Makefile.in b/xpcom/threads/Makefile.in index b209cf8970c..74bb86fd563 100644 --- a/xpcom/threads/Makefile.in +++ b/xpcom/threads/Makefile.in @@ -44,6 +44,7 @@ CSRCS = \ CPPSRCS = \ nsAutoLock.cpp \ + nsEnvironment.cpp \ nsEventQueue.cpp \ nsEventQueueService.cpp \ nsThread.cpp \ @@ -68,6 +69,7 @@ XPIDLSRCS = \ nsIEventTarget.idl \ nsIEventQueue.idl \ nsIEventQueueService.idl \ + nsIEnvironment.idl \ nsIProcess.idl \ $(NULL) diff --git a/xpcom/threads/nsEnvironment.cpp b/xpcom/threads/nsEnvironment.cpp new file mode 100644 index 00000000000..c29b5e5b4db --- /dev/null +++ b/xpcom/threads/nsEnvironment.cpp @@ -0,0 +1,202 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** 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 mozilla embedding code. + * + * The Initial Developers of the Original Code are + * Benjamin Smedberg and + * Roland Mainz . + * + * Portions created by the Initial Developer are Copyright (C) 2003/2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 "nsEnvironment.h" +#include "prenv.h" +#include "prprf.h" +#include "nsAutoLock.h" +#include "nsBaseHashtable.h" +#include "nsHashKeys.h" +#include "nsPromiseFlatString.h" +#include "nsDependentString.h" +#include "nsNativeCharsetUtils.h" + +NS_IMPL_THREADSAFE_ISUPPORTS1(nsEnvironment, nsIEnvironment) + +nsresult +nsEnvironment::Create(nsISupports *aOuter, REFNSIID aIID, + void **aResult) +{ + nsresult rv; + *aResult = nsnull; + + if (aOuter != nsnull) { + return NS_ERROR_NO_AGGREGATION; + } + + nsEnvironment* obj = new nsEnvironment(); + if (!obj) { + return NS_ERROR_OUT_OF_MEMORY; + } + + obj->mLock = PR_NewLock(); + if (!obj->mLock) { + delete obj; + return NS_ERROR_OUT_OF_MEMORY; + } + + rv = obj->QueryInterface(aIID, aResult); + if (NS_FAILED(rv)) { + delete obj; + } + return rv; +} + +nsEnvironment::~nsEnvironment() +{ + if (mLock) + PR_DestroyLock(mLock); +} + +NS_IMETHODIMP +nsEnvironment::Exists(const nsAString& aName, PRBool *aOutValue) +{ + nsCAutoString nativeName; + nsresult rv = NS_CopyUnicodeToNative(aName, nativeName); + NS_ENSURE_SUCCESS(rv, rv); + + nsCAutoString nativeVal; +#if defined(XP_UNIX) + /* For Unix/Linux platforms we follow the Unix definition: + * An environment variable exists when |getenv()| returns a non-NULL value. + * An environment variable does not exist when |getenv()| returns NULL. + */ + const char *value = PR_GetEnv(nativeName.get()); + + *aOutValue = (value)?(PR_TRUE):(PR_FALSE); +#else + /* For non-Unix/Linux platforms we have to fall back to a + * "portable" definition (which is incorrect for Unix/Linux!!!!) + * which simply checks whether the string returned by |Get()| is empty + * or not. + */ + nsAutoString value; + Get(aName, value); + *aOutValue = (value.IsEmpty())?(PR_FALSE):(PR_TRUE); +#endif /* XP_UNIX */ + + return NS_OK; +} + +NS_IMETHODIMP +nsEnvironment::Get(const nsAString& aName, nsAString& aOutValue) +{ + nsCAutoString nativeName; + nsresult rv = NS_CopyUnicodeToNative(aName, nativeName); + NS_ENSURE_SUCCESS(rv, rv); + + nsCAutoString nativeVal; + const char *value = PR_GetEnv(nativeName.get()); + if (value) { + rv = NS_CopyNativeToUnicode(nsDependentCString(value), aOutValue); + } else { + aOutValue.Truncate(); + rv = NS_OK; + } + + return rv; +} + +/* Environment strings must have static duration; We're gonna leak all of this + * at shutdown: this is by design, caused how Unix/Linux implement environment + * vars. + */ + +typedef nsBaseHashtableET EnvEntryType; +typedef nsTHashtable EnvHashType; + +static EnvHashType *gEnvHash = nsnull; + +static PRBool +EnsureEnvHash() +{ + if (gEnvHash) + return PR_TRUE; + + gEnvHash = new EnvHashType; + if (!gEnvHash) + return PR_FALSE; + + if(gEnvHash->Init()) + return PR_TRUE; + + delete gEnvHash; + gEnvHash = nsnull; + return PR_FALSE; +} + +NS_IMETHODIMP +nsEnvironment::Set(const nsAString& aName, const nsAString& aValue) +{ + nsCAutoString nativeName; + nsCAutoString nativeVal; + + nsresult rv = NS_CopyUnicodeToNative(aName, nativeName); + NS_ENSURE_SUCCESS(rv, rv); + + rv = NS_CopyUnicodeToNative(aValue, nativeVal); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoLock lock(mLock); // autolock unlocks automagically + + if (!EnsureEnvHash()){ + return NS_ERROR_UNEXPECTED; + } + + EnvEntryType* entry = gEnvHash->PutEntry(nativeName); + if (!entry) { + return NS_ERROR_OUT_OF_MEMORY; + } + + char* newData = PR_smprintf("%s=%s", + nativeName.get(), + nativeVal.get()); + if (!newData) { + return NS_ERROR_OUT_OF_MEMORY; + } + + PR_SetEnv(newData); + if (entry->mData) { + PR_smprintf_free(entry->mData); + } + entry->mData = newData; + return NS_OK; +} + + diff --git a/xpcom/threads/nsEnvironment.h b/xpcom/threads/nsEnvironment.h new file mode 100644 index 00000000000..4a35aac5d0c --- /dev/null +++ b/xpcom/threads/nsEnvironment.h @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** 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 mozilla embedding code. + * + * The Initial Developers of the Original Code are + * Benjamin Smedberg and + * Roland Mainz . + * + * Portions created by the Initial Developer are Copyright (C) 2003/2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 nsEnvironment_h__ +#define nsEnvironment_h__ + +#include "nsIEnvironment.h" +#include "prlock.h" + +#define NS_ENVIRONMENT_CID \ + { 0X3D68F92UL, 0X9513, 0X4E25, \ + { 0X9B, 0XE9, 0X7C, 0XB2, 0X39, 0X87, 0X41, 0X72 } } +#define NS_ENVIRONMENT_CONTRACTID "@mozilla.org/process/environment;1" + +class nsEnvironment : public nsIEnvironment +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIENVIRONMENT + + static nsresult Create(nsISupports *aOuter, REFNSIID aIID, + void **aResult); + +private: + nsEnvironment() { } + ~nsEnvironment(); + + PRLock *mLock; +}; + +#endif /* !nsEnvironment_h__ */ diff --git a/xpcom/threads/nsIEnvironment.idl b/xpcom/threads/nsIEnvironment.idl new file mode 100644 index 00000000000..953513461ef --- /dev/null +++ b/xpcom/threads/nsIEnvironment.idl @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** 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 mozilla embedding code. + * + * The Initial Developers of the Original Code are + * Benjamin Smedberg and + * Roland Mainz . + * + * Portions created by the Initial Developer are Copyright (C) 2003/2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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" + +/** + * Scriptable access to the current process environment. + * + */ +[scriptable, uuid(101d5941-d820-4e85-a266-9a3469940807)] +interface nsIEnvironment : nsISupports +{ + /** + * Set the value of an environment variable. + * + * @param aName the variable name to set. + * @param aValue the value to set. + */ + void set(in AString aName, in AString aValue); + + /** + * Get the value of an environment variable. + * + * @param aName the variable name to retrieve. + * @return returns the value of the env variable. An empty string + * will be returned when the env variable does not exist or + * when the value itself is an empty string - please use + * |exists()| to probe whether the env variable exists + * or not. + */ + AString get(in AString aName); + + /** + * Check the existence of an environment variable. + * This method checks whether an environment variable is present in + * the environment or not. + * + * - For Unix/Linux platforms we follow the Unix definition: + * An environment variable exists when |getenv()| returns a non-NULL value. + * An environment variable does not exist when |getenv()| returns NULL. + * - For non-Unix/Linux platforms we have to fall back to a + * "portable" definition (which is incorrect for Unix/Linux!!!!) + * which simply checks whether the string returned by |Get()| is empty + * or not. + * + * @param aName the variable name to probe. + * @return if the variable has been set, the value returned is + * PR_TRUE. If the variable was not defined in the + * environment PR_FALSE will be returned. + */ + boolean exists(in AString aName); +}; + diff --git a/xpcom/threads/nsIProcess.idl b/xpcom/threads/nsIProcess.idl index 1989d135938..ce5dca8eb0f 100644 --- a/xpcom/threads/nsIProcess.idl +++ b/xpcom/threads/nsIProcess.idl @@ -23,17 +23,6 @@ interface nsIProcess : nsISupports readonly attribute string processName; readonly attribute unsigned long processSignature; readonly attribute long exitValue; - - /** - * Called to get the value of environment variable - * XXX what charset? - * - * @param aName The string enviroment variable name - * @exception NS_ERROR_OUT_OF_MEMORY - * - * @return The value of the requested string environment variable name - */ - string getEnvironment(in string aName); }; %{C++ diff --git a/xpcom/threads/nsProcessCommon.cpp b/xpcom/threads/nsProcessCommon.cpp index b8a95163d2f..231ad44a7be 100644 --- a/xpcom/threads/nsProcessCommon.cpp +++ b/xpcom/threads/nsProcessCommon.cpp @@ -341,14 +341,3 @@ nsProcess::GetExitValue(PRInt32 *aExitValue) return NS_OK; } - -NS_IMETHODIMP -nsProcess::GetEnvironment(const char *aName, char **aValue) -{ - NS_ENSURE_ARG_POINTER(aName); - *aValue = nsCRT::strdup(PR_GetEnv(aName)); - if (!*aValue) - return NS_ERROR_OUT_OF_MEMORY; - return NS_OK; -} - diff --git a/xpcom/threads/nsProcessMac.cpp b/xpcom/threads/nsProcessMac.cpp index a2c1b8cbbea..9aad97a3c2d 100644 --- a/xpcom/threads/nsProcessMac.cpp +++ b/xpcom/threads/nsProcessMac.cpp @@ -135,17 +135,6 @@ NS_IMETHODIMP nsProcess::InitWithPid(PRUint32 pid) return NS_ERROR_NOT_IMPLEMENTED; } - -NS_IMETHODIMP -nsProcess::GetEnvironment(const char *aName, char **aValue) -{ - NS_ENSURE_ARG_POINTER(aName); - *aValue = nsCRT::strdup(PR_GetEnv(aName)); - if (!*aValue) - return NS_ERROR_OUT_OF_MEMORY; - return NS_OK; -} - NS_IMETHODIMP nsProcess::GetLocation(nsIFile** aLocation) {