move permission manager persistent storage from hostperm.1 to permissions.sqlite, use nsIURI::GetAsciiHost() for consistent host normalization, and expand type/permission limits. bugs 400092 and 400097 (patch in 400097), sr=shaver, pending r=sdwilsh, blocking-1.9+.

This commit is contained in:
dwitte@stanford.edu 2007-12-04 22:37:36 -08:00
parent 0e7d2c24a1
commit bd5df04b78
4 changed files with 567 additions and 691 deletions

View File

@ -62,6 +62,7 @@ REQUIRES = xpcom \
windowwatcher \
docshell \
appshell \
storage \
$(NULL)
CPPSRCS = \

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@ -20,6 +20,8 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Michiel van Leeuwen (mvl@exedo.nl)
* Daniel Witte (dwitte@stanford.edu)
*
* 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
@ -45,24 +47,28 @@
#include "nsCOMPtr.h"
#include "nsIFile.h"
#include "nsTHashtable.h"
#include "nsTArray.h"
#include "nsString.h"
#include "nsITimer.h"
class nsIPermission;
class nsIIDNService;
class mozIStorageConnection;
class mozIStorageStatement;
////////////////////////////////////////////////////////////////////////////////
// This allow us 8 types of permissions, with 256 values for each
// permission (some types might want to prompt, block 3rd party etc).
// Note that nsIPermissionManager.idl only allows 16 values for permission,
// and that nsPermissionManager::Write() can only deal with 26 values of
// permission safely. (We allow space for 256 here, since it's faster to
// deal with bytes than with bits).
// Note: When changing NUMBER_OF_TYPES, also update PermissionsAreEmpty()
// and the constructors.
// This should be a multiple of 4, to make PermissionsAreEmpty() fast
#define NUMBER_OF_TYPES (8)
#define NUMBER_OF_PERMISSIONS (16)
class nsPermissionEntry
{
public:
nsPermissionEntry(PRUint32 aType, PRUint32 aPermission, PRInt64 aID)
: mType(aType)
, mPermission(aPermission)
, mID(aID) {}
PRUint32 mType;
PRUint32 mPermission;
PRInt64 mID;
};
class nsHostEntry : public PLDHashEntryHdr
{
@ -100,7 +106,9 @@ public:
return PL_DHashStringKey(nsnull, aKey);
}
enum { ALLOW_MEMMOVE = PR_TRUE };
// force the hashtable to use the copy constructor when shuffling entries
// around, otherwise the Auto part of our nsAutoTArray won't be happy!
enum { ALLOW_MEMMOVE = PR_FALSE };
// Permissions methods
inline const nsDependentCString GetHost() const
@ -108,33 +116,32 @@ public:
return nsDependentCString(mHost);
}
// Callers must do boundary checks
void SetPermission(PRInt32 aTypeIndex, PRUint32 aPermission)
inline nsTArray<nsPermissionEntry> & GetPermissions()
{
mPermissions[aTypeIndex] = (PRUint8)aPermission;
return mPermissions;
}
PRUint32 GetPermission(PRInt32 aTypeIndex) const
inline PRInt32 GetPermissionIndex(PRUint32 aType) const
{
return (PRUint32)mPermissions[aTypeIndex];
for (PRUint32 i = 0; i < mPermissions.Length(); ++i)
if (mPermissions[i].mType == aType)
return i;
return -1;
}
PRBool PermissionsAreEmpty() const
inline PRUint32 GetPermission(PRUint32 aType) const
{
// Cast to PRUint32, to make this faster. Only 2 checks instead of 8
return (*reinterpret_cast<const PRUint32*>(&mPermissions[0])==0 &&
*reinterpret_cast<const PRUint32*>(&mPermissions[4])==0 );
for (PRUint32 i = 0; i < mPermissions.Length(); ++i)
if (mPermissions[i].mType == aType)
return mPermissions[i].mPermission;
return nsIPermissionManager::UNKNOWN_ACTION;
}
private:
const char *mHost;
// This will contain the permissions for different types, in a bitmasked
// form. The type itself defines the position.
// One byte per permission. This is a small loss of memory (as 255 types
// of action per type is a lot, 16 would be enough), but will improve speed
// Bytemasking is around twice as fast (on one arch at least) than bitmasking
PRUint8 mPermissions[NUMBER_OF_TYPES];
nsAutoTArray<nsPermissionEntry, 1> mPermissions;
};
@ -155,10 +162,31 @@ public:
private:
// enums for AddInternal()
enum OperationType {
eOperationNone,
eOperationAdding,
eOperationRemoving,
eOperationChanging
};
enum DBOperationType {
eNoDBOperation,
eWriteToDB
};
enum NotifyOperationType {
eDontNotify,
eNotify
};
nsresult AddInternal(const nsAFlatCString &aHost,
PRInt32 aTypeIndex,
const nsAFlatCString &aType,
PRUint32 aPermission,
PRBool aNotify);
PRInt64 aID,
NotifyOperationType aNotifyOperation,
DBOperationType aDBOperation);
PRInt32 GetTypeIndex(const char *aTypeString,
PRBool aAdd);
@ -171,32 +199,40 @@ private:
PRUint32 *aPermission,
PRBool aExactHostMatch);
// Use LazyWrite to save the permissions file on a timer. It will write
// the file only once if repeatedly hammered quickly.
void LazyWrite();
static void DoLazyWrite(nsITimer *aTimer, void *aClosure);
nsresult Write();
nsresult InitDB();
nsresult CreateTable();
nsresult Import();
nsresult Read();
void NotifyObserversWithPermission(const nsACString &aHost,
const char *aType,
const nsCString &aType,
PRUint32 aPermission,
const PRUnichar *aData);
void NotifyObservers(nsIPermission *aPermission, const PRUnichar *aData);
nsresult RemoveAllInternal();
nsresult RemoveAllFromMemory();
nsresult NormalizeToACE(nsCString &aHost);
nsresult GetHost(nsIURI *aURI, nsACString &aResult);
void RemoveTypeStrings();
static void UpdateDB(OperationType aOp,
mozIStorageStatement* aStmt,
PRInt64 aID,
const nsACString &aHost,
const nsACString &aType,
PRUint32 aPermission);
nsCOMPtr<nsIObserverService> mObserverService;
nsCOMPtr<nsIFile> mPermissionsFile;
nsCOMPtr<nsITimer> mWriteTimer;
nsCOMPtr<nsIIDNService> mIDNService;
nsCOMPtr<mozIStorageConnection> mDBConn;
nsCOMPtr<mozIStorageStatement> mStmtInsert;
nsCOMPtr<mozIStorageStatement> mStmtDelete;
nsCOMPtr<mozIStorageStatement> mStmtUpdate;
nsTHashtable<nsHostEntry> mHostTable;
PRUint32 mHostCount;
PRPackedBool mChangedList;
PRPackedBool mHasUnknownTypes;
// a unique, monotonically increasing id used to identify each database entry
PRInt64 mLargestID;
// An array to store the strings identifying the different types.
char *mTypeArray[NUMBER_OF_TYPES];
nsTArray<nsCString> mTypeArray;
};
// {4F6B5E00-0C36-11d5-A535-0010A401EB10}

View File

@ -72,6 +72,9 @@ interface nsIPermissionManager : nsISupports
/**
* Predefined return values for the testPermission method and for
* the permission param of the add method
* NOTE: UNKNOWN_ACTION (0) is reserved to represent the
* default permission when no entry is found for a host, and
* should not be used by consumers to indicate otherwise.
*/
const PRUint32 UNKNOWN_ACTION = 0;
const PRUint32 ALLOW_ACTION = 1;
@ -80,30 +83,31 @@ interface nsIPermissionManager : nsISupports
/**
* Add permission information for a given URI and permission type. This
* operation will cause the type string to be registered if it does not
* currently exist.
* currently exist. If a permission already exists for a given type, it
* will be modified.
*
* @param uri the uri to add the permission for
* @param type a case-sensitive ASCII string, identifying the consumer.
* Consumers should choose this string to be unique, with
* respect to other consumers. The number of unique type
* identifiers may be limited.
* @param permission an integer from 1 to 15, representing the desired
* action (e.g. allow or deny). The interpretation of
* this number is up to the consumer, and may represent
* different actions for different types. Consumers may
* use one of the enumerated permission actions defined
* above. 0 is reserved for UNKNOWN_ACTION, and shouldn't
* be used.
* @throws NS_ERROR_FAILURE if there is no more room for adding
* a new type
* respect to other consumers.
* @param permission an integer representing the desired action (e.g. allow
* or deny). The interpretation of this number is up to the
* consumer, and may represent different actions for different
* types. Consumers may use one of the enumerated permission
* actions defined above, for convenience.
* NOTE: UNKNOWN_ACTION (0) is reserved to represent the
* default permission when no entry is found for a host, and
* should not be used by consumers to indicate otherwise.
*/
void add(in nsIURI uri,
in string type,
in PRUint32 permission);
/**
* Remove permission information for a given URI and permission type.
* Note that this method takes a host string, not an nsIURI.
* Remove permission information for a given host string and permission type.
* The host string represents the exact entry in the permission list (such as
* obtained from the enumerator), not a URI which that permission might apply
* to.
*
* @param host the host to remove the permission for
* @param type a case-sensitive ASCII string, identifying the consumer.