Bug 580790 - Connection::initialize can access preferences off of the main thread

Makes things go boom when preferences are accessed off of the main thread.
r=dwitte
sr=bsmedberg
a=blocking2.0
This commit is contained in:
Shawn Wilsher 2010-08-06 10:27:58 -07:00
Родитель eae666cad7
Коммит 0ddeef5779
3 изменённых файлов: 126 добавлений и 1 удалений

Просмотреть файл

@ -44,6 +44,7 @@
#endif
#include "nsPrefBranch.h"
#include "nsPrefService.h"
#include "nsILocalFile.h"
#include "nsIObserverService.h"
#include "nsXPCOM.h"
@ -52,6 +53,7 @@
#include "nsString.h"
#include "nsReadableUtils.h"
#include "nsXPIDLString.h"
#include "nsThreadUtils.h"
#include "nsIStringBundle.h"
#include "prefapi.h"
#include "prmem.h"
@ -153,6 +155,9 @@ NS_INTERFACE_MAP_END
NS_IMETHODIMP nsPrefBranch::GetRoot(char **aRoot)
{
NS_ENSURE_ARG_POINTER(aRoot);
if (NS_UNLIKELY(!nsPrefService::CheckAndLogBackgroundThreadUse())) {
return NS_ERROR_UNEXPECTED;
}
mPrefRoot.Truncate(mPrefRootLength);
*aRoot = ToNewCString(mPrefRoot);
@ -161,6 +166,10 @@ NS_IMETHODIMP nsPrefBranch::GetRoot(char **aRoot)
NS_IMETHODIMP nsPrefBranch::GetPrefType(const char *aPrefName, PRInt32 *_retval)
{
if (NS_UNLIKELY(!nsPrefService::CheckAndLogBackgroundThreadUse())) {
return NS_ERROR_UNEXPECTED;
}
#ifdef MOZ_IPC
if (ContentChild* cpc = GetContentChild()) {
nsresult rv = NS_ERROR_NOT_AVAILABLE;
@ -179,6 +188,10 @@ NS_IMETHODIMP nsPrefBranch::GetPrefType(const char *aPrefName, PRInt32 *_retval)
NS_IMETHODIMP nsPrefBranch::GetBoolPref(const char *aPrefName, PRBool *_retval)
{
if (NS_UNLIKELY(!nsPrefService::CheckAndLogBackgroundThreadUse())) {
return NS_ERROR_UNEXPECTED;
}
#ifdef MOZ_IPC
if (ContentChild* cpc = GetContentChild()) {
nsresult rv = NS_ERROR_NOT_AVAILABLE;
@ -196,6 +209,10 @@ NS_IMETHODIMP nsPrefBranch::GetBoolPref(const char *aPrefName, PRBool *_retval)
NS_IMETHODIMP nsPrefBranch::SetBoolPref(const char *aPrefName, PRInt32 aValue)
{
if (NS_UNLIKELY(!nsPrefService::CheckAndLogBackgroundThreadUse())) {
return NS_ERROR_UNEXPECTED;
}
#ifdef MOZ_IPC
if (GetContentChild()) {
NS_ERROR("cannot set pref from content process");
@ -209,6 +226,10 @@ NS_IMETHODIMP nsPrefBranch::SetBoolPref(const char *aPrefName, PRInt32 aValue)
NS_IMETHODIMP nsPrefBranch::GetCharPref(const char *aPrefName, char **_retval)
{
if (NS_UNLIKELY(!nsPrefService::CheckAndLogBackgroundThreadUse())) {
return NS_ERROR_UNEXPECTED;
}
#ifdef MOZ_IPC
if (ContentChild* cpc = GetContentChild()) {
nsresult rv = NS_ERROR_NOT_AVAILABLE;
@ -228,6 +249,10 @@ NS_IMETHODIMP nsPrefBranch::GetCharPref(const char *aPrefName, char **_retval)
NS_IMETHODIMP nsPrefBranch::SetCharPref(const char *aPrefName, const char *aValue)
{
if (NS_UNLIKELY(!nsPrefService::CheckAndLogBackgroundThreadUse())) {
return NS_ERROR_UNEXPECTED;
}
#ifdef MOZ_IPC
if (GetContentChild()) {
NS_ERROR("cannot set pref from content process");
@ -241,6 +266,10 @@ NS_IMETHODIMP nsPrefBranch::SetCharPref(const char *aPrefName, const char *aValu
NS_IMETHODIMP nsPrefBranch::GetIntPref(const char *aPrefName, PRInt32 *_retval)
{
if (NS_UNLIKELY(!nsPrefService::CheckAndLogBackgroundThreadUse())) {
return NS_ERROR_UNEXPECTED;
}
#ifdef MOZ_IPC
if (ContentChild* cpc = GetContentChild()) {
nsresult rv = NS_ERROR_NOT_AVAILABLE;
@ -258,6 +287,10 @@ NS_IMETHODIMP nsPrefBranch::GetIntPref(const char *aPrefName, PRInt32 *_retval)
NS_IMETHODIMP nsPrefBranch::SetIntPref(const char *aPrefName, PRInt32 aValue)
{
if (NS_UNLIKELY(!nsPrefService::CheckAndLogBackgroundThreadUse())) {
return NS_ERROR_UNEXPECTED;
}
#ifdef MOZ_IPC
if (GetContentChild()) {
NS_ERROR("cannot set pref from content process");
@ -271,6 +304,10 @@ NS_IMETHODIMP nsPrefBranch::SetIntPref(const char *aPrefName, PRInt32 aValue)
NS_IMETHODIMP nsPrefBranch::GetComplexValue(const char *aPrefName, const nsIID & aType, void **_retval)
{
if (NS_UNLIKELY(!nsPrefService::CheckAndLogBackgroundThreadUse())) {
return NS_ERROR_UNEXPECTED;
}
nsresult rv;
nsXPIDLCString utf8String;
@ -445,6 +482,10 @@ NS_IMETHODIMP nsPrefBranch::GetComplexValue(const char *aPrefName, const nsIID &
NS_IMETHODIMP nsPrefBranch::SetComplexValue(const char *aPrefName, const nsIID & aType, nsISupports *aValue)
{
if (NS_UNLIKELY(!nsPrefService::CheckAndLogBackgroundThreadUse())) {
return NS_ERROR_UNEXPECTED;
}
#ifdef MOZ_IPC
if (GetContentChild()) {
NS_ERROR("cannot set pref from content process");
@ -534,6 +575,10 @@ NS_IMETHODIMP nsPrefBranch::SetComplexValue(const char *aPrefName, const nsIID &
NS_IMETHODIMP nsPrefBranch::ClearUserPref(const char *aPrefName)
{
if (NS_UNLIKELY(!nsPrefService::CheckAndLogBackgroundThreadUse())) {
return NS_ERROR_UNEXPECTED;
}
#ifdef MOZ_IPC
if (GetContentChild()) {
NS_ERROR("cannot set pref from content process");
@ -548,6 +593,9 @@ NS_IMETHODIMP nsPrefBranch::ClearUserPref(const char *aPrefName)
NS_IMETHODIMP nsPrefBranch::PrefHasUserValue(const char *aPrefName, PRBool *_retval)
{
NS_ENSURE_ARG_POINTER(_retval);
if (NS_UNLIKELY(!nsPrefService::CheckAndLogBackgroundThreadUse())) {
return NS_ERROR_UNEXPECTED;
}
#ifdef MOZ_IPC
if (ContentChild* cpc = GetContentChild()) {
@ -567,6 +615,10 @@ NS_IMETHODIMP nsPrefBranch::PrefHasUserValue(const char *aPrefName, PRBool *_ret
NS_IMETHODIMP nsPrefBranch::LockPref(const char *aPrefName)
{
if (NS_UNLIKELY(!nsPrefService::CheckAndLogBackgroundThreadUse())) {
return NS_ERROR_UNEXPECTED;
}
#ifdef MOZ_IPC
if (GetContentChild()) {
NS_ERROR("cannot lock pref from content process");
@ -581,6 +633,9 @@ NS_IMETHODIMP nsPrefBranch::LockPref(const char *aPrefName)
NS_IMETHODIMP nsPrefBranch::PrefIsLocked(const char *aPrefName, PRBool *_retval)
{
NS_ENSURE_ARG_POINTER(_retval);
if (NS_UNLIKELY(!nsPrefService::CheckAndLogBackgroundThreadUse())) {
return NS_ERROR_UNEXPECTED;
}
#ifdef MOZ_IPC
if (ContentChild* cpc = GetContentChild()) {
@ -600,6 +655,10 @@ NS_IMETHODIMP nsPrefBranch::PrefIsLocked(const char *aPrefName, PRBool *_retval)
NS_IMETHODIMP nsPrefBranch::UnlockPref(const char *aPrefName)
{
if (NS_UNLIKELY(!nsPrefService::CheckAndLogBackgroundThreadUse())) {
return NS_ERROR_UNEXPECTED;
}
#ifdef MOZ_IPC
if (GetContentChild()) {
NS_ERROR("cannot unlock pref from content process");
@ -619,6 +678,10 @@ NS_IMETHODIMP nsPrefBranch::ResetBranch(const char *aStartingAt)
NS_IMETHODIMP nsPrefBranch::DeleteBranch(const char *aStartingAt)
{
if (NS_UNLIKELY(!nsPrefService::CheckAndLogBackgroundThreadUse())) {
return NS_ERROR_UNEXPECTED;
}
#ifdef MOZ_IPC
if (GetContentChild()) {
NS_ERROR("cannot set pref from content process");
@ -632,6 +695,10 @@ NS_IMETHODIMP nsPrefBranch::DeleteBranch(const char *aStartingAt)
NS_IMETHODIMP nsPrefBranch::GetChildList(const char *aStartingAt, PRUint32 *aCount, char ***aChildArray)
{
if (NS_UNLIKELY(!nsPrefService::CheckAndLogBackgroundThreadUse())) {
return NS_ERROR_UNEXPECTED;
}
char **outArray;
PRInt32 numPrefs;
PRInt32 dwIndex;
@ -702,6 +769,10 @@ NS_IMETHODIMP nsPrefBranch::GetChildList(const char *aStartingAt, PRUint32 *aCou
NS_IMETHODIMP nsPrefBranch::AddObserver(const char *aDomain, nsIObserver *aObserver, PRBool aHoldWeak)
{
if (NS_UNLIKELY(!nsPrefService::CheckAndLogBackgroundThreadUse())) {
return NS_ERROR_UNEXPECTED;
}
PrefCallbackData *pCallback;
const char *pref;
@ -767,6 +838,9 @@ NS_IMETHODIMP nsPrefBranch::RemoveObserver(const char *aDomain, nsIObserver *aOb
{
NS_ENSURE_ARG_POINTER(aDomain);
NS_ENSURE_ARG_POINTER(aObserver);
if (NS_UNLIKELY(!nsPrefService::CheckAndLogBackgroundThreadUse())) {
return NS_ERROR_UNEXPECTED;
}
#ifdef MOZ_IPC
if (XRE_GetProcessType() == GeckoProcessType_Content) {

Просмотреть файл

@ -45,6 +45,7 @@
#include "nsAppDirectoryServiceDefs.h"
#include "nsDirectoryServiceDefs.h"
#include "nsICategoryManager.h"
#include "nsIConsoleService.h"
#include "nsCategoryManagerUtils.h"
#include "nsNetUtil.h"
#include "nsIFile.h"
@ -56,6 +57,7 @@
#include "nsCOMArray.h"
#include "nsXPCOMCID.h"
#include "nsAutoPtr.h"
#include "nsThreadUtils.h"
#include "nsQuickSort.h"
#include "prmem.h"
@ -199,6 +201,10 @@ NS_IMETHODIMP nsPrefService::Observe(nsISupports *aSubject, const char *aTopic,
NS_IMETHODIMP nsPrefService::ReadUserPrefs(nsIFile *aFile)
{
if (NS_UNLIKELY(!CheckAndLogBackgroundThreadUse())) {
return NS_ERROR_UNEXPECTED;
}
#ifdef MOZ_IPC
if (XRE_GetProcessType() == GeckoProcessType_Content) {
NS_ERROR("cannot load prefs from content process");
@ -222,6 +228,10 @@ NS_IMETHODIMP nsPrefService::ReadUserPrefs(nsIFile *aFile)
NS_IMETHODIMP nsPrefService::ResetPrefs()
{
if (NS_UNLIKELY(!CheckAndLogBackgroundThreadUse())) {
return NS_ERROR_UNEXPECTED;
}
#ifdef MOZ_IPC
if (XRE_GetProcessType() == GeckoProcessType_Content) {
NS_ERROR("cannot set prefs from content process");
@ -240,6 +250,10 @@ NS_IMETHODIMP nsPrefService::ResetPrefs()
NS_IMETHODIMP nsPrefService::ResetUserPrefs()
{
if (NS_UNLIKELY(!CheckAndLogBackgroundThreadUse())) {
return NS_ERROR_UNEXPECTED;
}
#ifdef MOZ_IPC
if (XRE_GetProcessType() == GeckoProcessType_Content) {
NS_ERROR("cannot set prefs from content process");
@ -253,6 +267,10 @@ NS_IMETHODIMP nsPrefService::ResetUserPrefs()
NS_IMETHODIMP nsPrefService::SavePrefFile(nsIFile *aFile)
{
if (NS_UNLIKELY(!CheckAndLogBackgroundThreadUse())) {
return NS_ERROR_UNEXPECTED;
}
#ifdef MOZ_IPC
if (XRE_GetProcessType() == GeckoProcessType_Content) {
NS_ERROR("cannot save prefs from content process");
@ -265,6 +283,10 @@ NS_IMETHODIMP nsPrefService::SavePrefFile(nsIFile *aFile)
NS_IMETHODIMP nsPrefService::GetBranch(const char *aPrefRoot, nsIPrefBranch **_retval)
{
if (NS_UNLIKELY(!CheckAndLogBackgroundThreadUse())) {
return NS_ERROR_UNEXPECTED;
}
nsresult rv;
if ((nsnull != aPrefRoot) && (*aPrefRoot != '\0')) {
@ -283,6 +305,10 @@ NS_IMETHODIMP nsPrefService::GetBranch(const char *aPrefRoot, nsIPrefBranch **_r
NS_IMETHODIMP nsPrefService::GetDefaultBranch(const char *aPrefRoot, nsIPrefBranch **_retval)
{
if (NS_UNLIKELY(!CheckAndLogBackgroundThreadUse())) {
return NS_ERROR_UNEXPECTED;
}
nsresult rv;
// TODO: - cache this stuff and allow consumers to share branches (hold weak references I think)
@ -802,3 +828,22 @@ static nsresult pref_InitInitialObjects()
return pref_LoadPrefsInDirList(NS_EXT_PREFS_DEFAULTS_DIR_LIST);
}
// static
bool
nsPrefService::CheckAndLogBackgroundThreadUse()
{
if (NS_IsMainThread()) {
return true;
}
NS_ERROR("Cannot be used on a background thread!");
nsCOMPtr<nsIConsoleService> cs =
do_GetService("@mozilla.org/consoleservice;1");
if (cs) {
(void)cs->LogStringMessage(NS_LITERAL_STRING(
"Invalid use of the preferences on a background thread!"
).get());
}
return false;
}

Просмотреть файл

@ -65,7 +65,13 @@ public:
virtual ~nsPrefService();
nsresult Init();
/**
* Checks to make sure we are on the main thread and log if we are not.
*
* @returns true if on the main thread, and false otherwise.
*/
static bool CheckAndLogBackgroundThreadUse();
protected:
nsresult NotifyServiceObservers(const char *aSubject);
nsresult UseDefaultPrefFile();