зеркало из https://github.com/mozilla/pjs.git
Bug 341524, DOM storage should follow cookie prefs
This commit is contained in:
Родитель
f40cf39e9a
Коммит
8769e463a9
|
@ -1671,16 +1671,13 @@ nsDocShell::HistoryPurged(PRInt32 aNumEntries)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::GetSessionStorageForDomain(const nsACString& aDomain,
|
||||
nsDocShell::GetSessionStorageForURI(nsIURI* aURI,
|
||||
nsIDOMStorage** aStorage)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aStorage);
|
||||
|
||||
*aStorage = nsnull;
|
||||
|
||||
if (aDomain.IsEmpty())
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> topItem;
|
||||
nsresult rv = GetSameTypeRootTreeItem(getter_AddRefs(topItem));
|
||||
if (NS_FAILED(rv))
|
||||
|
@ -1691,9 +1688,16 @@ nsDocShell::GetSessionStorageForDomain(const nsACString& aDomain,
|
|||
|
||||
nsCOMPtr<nsIDocShell> topDocShell = do_QueryInterface(topItem);
|
||||
if (topDocShell != this)
|
||||
return topDocShell->GetSessionStorageForDomain(aDomain, aStorage);
|
||||
return topDocShell->GetSessionStorageForURI(aURI, aStorage);
|
||||
|
||||
if (!mStorages.Get(aDomain, aStorage)) {
|
||||
nsCAutoString currentDomain;
|
||||
rv = aURI->GetAsciiHost(currentDomain);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (currentDomain.IsEmpty())
|
||||
return NS_OK;
|
||||
|
||||
if (!mStorages.Get(currentDomain, aStorage)) {
|
||||
nsCOMPtr<nsIDOMStorage> newstorage =
|
||||
do_CreateInstance("@mozilla.org/dom/storage;1");
|
||||
if (!newstorage)
|
||||
|
@ -1702,9 +1706,9 @@ nsDocShell::GetSessionStorageForDomain(const nsACString& aDomain,
|
|||
nsCOMPtr<nsPIDOMStorage> pistorage = do_QueryInterface(newstorage);
|
||||
if (!pistorage)
|
||||
return NS_ERROR_FAILURE;
|
||||
pistorage->Init(NS_ConvertUTF8toUTF16(aDomain), PR_FALSE);
|
||||
pistorage->Init(aURI, NS_ConvertUTF8toUTF16(currentDomain), PR_FALSE);
|
||||
|
||||
if (!mStorages.Put(aDomain, newstorage))
|
||||
if (!mStorages.Put(currentDomain, newstorage))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
*aStorage = newstorage;
|
||||
|
@ -6441,13 +6445,13 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
|||
gethostrv |= aURI->GetAsciiHost(newDomain);
|
||||
if (NS_SUCCEEDED(gethostrv) && thisDomain.Equals(newDomain)) {
|
||||
nsCOMPtr<nsIDOMStorage> storage;
|
||||
GetSessionStorageForDomain(thisDomain,
|
||||
GetSessionStorageForURI(currentCodebase,
|
||||
getter_AddRefs(storage));
|
||||
nsCOMPtr<nsPIDOMStorage> piStorage =
|
||||
do_QueryInterface(storage);
|
||||
if (piStorage) {
|
||||
nsCOMPtr<nsIDOMStorage> newstorage =
|
||||
piStorage->Clone();
|
||||
piStorage->Clone(currentCodebase);
|
||||
targetDocShell->AddSessionStorage(thisDomain,
|
||||
newstorage);
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ interface nsILayoutHistoryState;
|
|||
interface nsISecureBrowserUI;
|
||||
interface nsIDOMStorage;
|
||||
|
||||
[scriptable, uuid(51241d7c-73c9-4b85-970c-bd4f91acfbcc)]
|
||||
[scriptable, uuid(539355C0-F5C8-4929-A4AA-CB105E8F9997)]
|
||||
interface nsIDocShell : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -417,7 +417,7 @@ interface nsIDocShell : nsISupports
|
|||
*
|
||||
* @param domain the domain of the storage object to retrieve
|
||||
*/
|
||||
nsIDOMStorage getSessionStorageForDomain(in ACString aDomain);
|
||||
nsIDOMStorage getSessionStorageForURI(in nsIURI uri);
|
||||
|
||||
/*
|
||||
* Add a WebApps session storage object to the docshell.
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "nsTArray.h"
|
||||
|
||||
class nsIDOMStorage;
|
||||
class nsIURI;
|
||||
|
||||
#define NS_PIDOMSTORAGE_IID \
|
||||
{ 0x2fdbb82e, 0x4b47, 0x406a, \
|
||||
|
@ -54,9 +55,9 @@ class nsPIDOMStorage : public nsISupports
|
|||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_PIDOMSTORAGE_IID)
|
||||
|
||||
virtual void Init(const nsAString &aDomain, PRBool aUseDB) = 0;
|
||||
virtual void Init(nsIURI* aURI, const nsAString &aDomain, PRBool aUseDB) = 0;
|
||||
|
||||
virtual already_AddRefed<nsIDOMStorage> Clone() = 0;
|
||||
virtual already_AddRefed<nsIDOMStorage> Clone(nsIURI* aURI) = 0;
|
||||
|
||||
virtual nsTArray<nsString> *GetKeys() = 0;
|
||||
};
|
||||
|
|
|
@ -5621,11 +5621,7 @@ nsGlobalWindow::GetSessionStorage(nsIDOMStorage ** aSessionStorage)
|
|||
return NS_FAILED(rv) ? rv : NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
||||
}
|
||||
|
||||
nsCAutoString currentDomain;
|
||||
rv = codebase->GetAsciiHost(currentDomain);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return docShell->GetSessionStorageForDomain(currentDomain, aSessionStorage);
|
||||
return docShell->GetSessionStorageForURI(codebase, aSessionStorage);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -6139,11 +6135,11 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
|
|||
|
||||
if (NS_SUCCEEDED(gethostrv) && thisDomain.Equals(newDomain)) {
|
||||
nsCOMPtr<nsIDOMStorage> storage;
|
||||
mDocShell->GetSessionStorageForDomain(thisDomain,
|
||||
mDocShell->GetSessionStorageForURI(currentCodebase,
|
||||
getter_AddRefs(storage));
|
||||
nsCOMPtr<nsPIDOMStorage> piStorage = do_QueryInterface(storage);
|
||||
if (piStorage) {
|
||||
nsCOMPtr<nsIDOMStorage> newstorage = piStorage->Clone();
|
||||
nsCOMPtr<nsIDOMStorage> newstorage = piStorage->Clone(newURI);
|
||||
newDocShell->AddSessionStorage(thisDomain, newstorage);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,18 @@
|
|||
#include "nsReadableUtils.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsICookiePermission.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
|
||||
static const PRUint32 ASK_BEFORE_ACCEPT = 1;
|
||||
static const PRUint32 ACCEPT_SESSION = 2;
|
||||
static const PRUint32 BEHAVIOR_REJECT = 2;
|
||||
|
||||
static const char kPermissionType[] = "cookie";
|
||||
static const char kStorageEnabled[] = "dom.storage.enabled";
|
||||
static const char kCookiesBehavior[] = "network.cookie.cookieBehavior";
|
||||
static const char kCookiesLifetimePolicy[] = "network.cookie.lifetimePolicy";
|
||||
|
||||
//
|
||||
// Helper that tells us whether the caller is secure or not.
|
||||
|
@ -135,13 +147,17 @@ NS_NewDOMStorage(nsISupports* aOuter, REFNSIID aIID, void** aResult)
|
|||
}
|
||||
|
||||
nsDOMStorage::nsDOMStorage()
|
||||
: mUseDB(PR_FALSE), mItemsCached(PR_FALSE)
|
||||
: mUseDB(PR_FALSE), mSessionOnly(PR_TRUE), mItemsCached(PR_FALSE)
|
||||
{
|
||||
mItems.Init(8);
|
||||
}
|
||||
|
||||
nsDOMStorage::nsDOMStorage(const nsAString& aDomain, PRBool aUseDB)
|
||||
: mUseDB(aUseDB), mItemsCached(PR_FALSE), mDomain(aDomain)
|
||||
nsDOMStorage::nsDOMStorage(nsIURI* aURI, const nsAString& aDomain, PRBool aUseDB)
|
||||
: mUseDB(aUseDB),
|
||||
mSessionOnly(PR_TRUE),
|
||||
mItemsCached(PR_FALSE),
|
||||
mURI(aURI),
|
||||
mDomain(aDomain)
|
||||
{
|
||||
#ifndef MOZ_STORAGE
|
||||
mUseDB = PR_FALSE;
|
||||
|
@ -155,8 +171,9 @@ nsDOMStorage::~nsDOMStorage()
|
|||
}
|
||||
|
||||
void
|
||||
nsDOMStorage::Init(const nsAString& aDomain, PRBool aUseDB)
|
||||
nsDOMStorage::Init(nsIURI* aURI, const nsAString& aDomain, PRBool aUseDB)
|
||||
{
|
||||
mURI = aURI;
|
||||
mDomain.Assign(aDomain);
|
||||
#ifdef MOZ_STORAGE
|
||||
mUseDB = aUseDB;
|
||||
|
@ -165,6 +182,48 @@ nsDOMStorage::Init(const nsAString& aDomain, PRBool aUseDB)
|
|||
#endif
|
||||
}
|
||||
|
||||
//static
|
||||
PRBool
|
||||
nsDOMStorage::CanUseStorage(nsIURI* aURI, PRPackedBool* aSessionOnly)
|
||||
{
|
||||
// check if the domain can use storage. Downgrade to session only if only
|
||||
// session storage may be used.
|
||||
NS_ASSERTION(aURI && aSessionOnly, "null URI or session flag");
|
||||
|
||||
if (!nsContentUtils::GetBoolPref(kStorageEnabled))
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIPermissionManager> permissionManager =
|
||||
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
|
||||
if (!permissionManager)
|
||||
return PR_FALSE;
|
||||
|
||||
*aSessionOnly = PR_FALSE;
|
||||
|
||||
PRUint32 perm;
|
||||
permissionManager->TestPermission(aURI, kPermissionType, &perm);
|
||||
|
||||
if (perm == nsIPermissionManager::DENY_ACTION)
|
||||
return PR_FALSE;
|
||||
|
||||
if (perm == nsICookiePermission::ACCESS_SESSION) {
|
||||
*aSessionOnly = PR_TRUE;
|
||||
}
|
||||
else if (perm != nsIPermissionManager::ALLOW_ACTION) {
|
||||
PRUint32 cookieBehavior = nsContentUtils::GetIntPref(kCookiesBehavior);
|
||||
PRUint32 lifetimePolicy = nsContentUtils::GetIntPref(kCookiesLifetimePolicy);
|
||||
|
||||
// treat ask as reject always
|
||||
if (cookieBehavior == BEHAVIOR_REJECT || lifetimePolicy == ASK_BEFORE_ACCEPT)
|
||||
return PR_FALSE;
|
||||
|
||||
if (lifetimePolicy == ACCEPT_SESSION)
|
||||
*aSessionOnly = PR_TRUE;
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
class ItemCounterState
|
||||
{
|
||||
public:
|
||||
|
@ -194,7 +253,10 @@ ItemCounter(nsSessionStorageEntry* aEntry, void* userArg)
|
|||
NS_IMETHODIMP
|
||||
nsDOMStorage::GetLength(PRUint32 *aLength)
|
||||
{
|
||||
if (mUseDB)
|
||||
if (!CacheStoragePermissions())
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
|
||||
if (UseDB())
|
||||
CacheKeysFromDB();
|
||||
|
||||
ItemCounterState state(IsCallerSecure());
|
||||
|
@ -253,7 +315,10 @@ nsDOMStorage::Key(PRUint32 aIndex, nsAString& aKey)
|
|||
// maybe we need to have a lazily populated key array here or
|
||||
// something?
|
||||
|
||||
if (mUseDB)
|
||||
if (!CacheStoragePermissions())
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
|
||||
if (UseDB())
|
||||
CacheKeysFromDB();
|
||||
|
||||
IndexFinderData data(IsCallerSecure(), aIndex);
|
||||
|
@ -274,6 +339,9 @@ nsDOMStorage::GetItem(const nsAString& aKey, nsIDOMStorageItem **aItem)
|
|||
{
|
||||
*aItem = nsnull;
|
||||
|
||||
if (!CacheStoragePermissions())
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
|
||||
if (aKey.IsEmpty())
|
||||
return NS_OK;
|
||||
|
||||
|
@ -285,7 +353,7 @@ nsDOMStorage::GetItem(const nsAString& aKey, nsIDOMStorageItem **aItem)
|
|||
}
|
||||
NS_ADDREF(*aItem = entry->mItem);
|
||||
}
|
||||
else if (mUseDB) {
|
||||
else if (UseDB()) {
|
||||
PRBool secure;
|
||||
nsAutoString value;
|
||||
nsresult rv = GetDBValue(aKey, value, &secure);
|
||||
|
@ -295,7 +363,7 @@ nsDOMStorage::GetItem(const nsAString& aKey, nsIDOMStorageItem **aItem)
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsRefPtr<nsDOMStorageItem> newitem =
|
||||
new nsDOMStorageItem(this, aKey, secure);
|
||||
new nsDOMStorageItem(this, aKey, value, secure);
|
||||
if (!newitem)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
|
@ -312,6 +380,9 @@ nsDOMStorage::GetItem(const nsAString& aKey, nsIDOMStorageItem **aItem)
|
|||
NS_IMETHODIMP
|
||||
nsDOMStorage::SetItem(const nsAString& aKey, const nsAString& aData)
|
||||
{
|
||||
if (!CacheStoragePermissions())
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
|
||||
if (aKey.IsEmpty())
|
||||
return NS_OK;
|
||||
|
||||
|
@ -322,21 +393,20 @@ nsDOMStorage::SetItem(const nsAString& aKey, const nsAString& aData)
|
|||
if (entry->mItem->IsSecure() && !IsCallerSecure()) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
if (!mUseDB) {
|
||||
rv = entry->mItem->SetValue(aData);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!UseDB()) {
|
||||
entry->mItem->SetValueInternal(aData);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (mUseDB)
|
||||
newitem = new nsDOMStorageItem(this, aKey, PR_FALSE);
|
||||
if (UseDB())
|
||||
newitem = new nsDOMStorageItem(this, aKey, aData, PR_FALSE);
|
||||
else
|
||||
newitem = new nsDOMStorageItem(nsnull, aData, PR_FALSE);
|
||||
newitem = new nsDOMStorageItem(this, aKey, aData, PR_FALSE);
|
||||
if (!newitem)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (mUseDB) {
|
||||
if (UseDB()) {
|
||||
rv = SetDBValue(aKey, aData, IsCallerSecure());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
@ -348,7 +418,7 @@ nsDOMStorage::SetItem(const nsAString& aKey, const nsAString& aData)
|
|||
}
|
||||
|
||||
// SetDBValue already calls BroadcastChangeNotification so don't do it again
|
||||
if (!mUseDB)
|
||||
if (!UseDB())
|
||||
BroadcastChangeNotification();
|
||||
|
||||
return NS_OK;
|
||||
|
@ -356,6 +426,9 @@ nsDOMStorage::SetItem(const nsAString& aKey, const nsAString& aData)
|
|||
|
||||
NS_IMETHODIMP nsDOMStorage::RemoveItem(const nsAString& aKey)
|
||||
{
|
||||
if (!CacheStoragePermissions())
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
|
||||
if (aKey.IsEmpty())
|
||||
return NS_OK;
|
||||
|
||||
|
@ -365,7 +438,7 @@ NS_IMETHODIMP nsDOMStorage::RemoveItem(const nsAString& aKey)
|
|||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
if (mUseDB) {
|
||||
if (UseDB()) {
|
||||
#ifdef MOZ_STORAGE
|
||||
nsresult rv = InitDB();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -453,8 +526,8 @@ nsDOMStorage::GetDBValue(const nsAString& aKey, nsAString& aValue,
|
|||
aValue.Truncate();
|
||||
|
||||
#ifdef MOZ_STORAGE
|
||||
NS_ASSERTION(mUseDB,
|
||||
"Uh, we should only get here if we're using the database!");
|
||||
if (!UseDB())
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv = InitDB();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -480,8 +553,8 @@ nsDOMStorage::SetDBValue(const nsAString& aKey,
|
|||
PRBool aSecure)
|
||||
{
|
||||
#ifdef MOZ_STORAGE
|
||||
NS_ASSERTION(mUseDB,
|
||||
"Uh, we should only get here if we're using the database!");
|
||||
if (!UseDB())
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv = InitDB();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -502,7 +575,7 @@ nsresult
|
|||
nsDOMStorage::SetSecure(const nsAString& aKey, PRBool aSecure)
|
||||
{
|
||||
#ifdef MOZ_STORAGE
|
||||
if (mUseDB) {
|
||||
if (UseDB()) {
|
||||
nsresult rv = InitDB();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
@ -537,15 +610,15 @@ CopyStorageItems(nsSessionStorageEntry* aEntry, void* userArg)
|
|||
}
|
||||
|
||||
already_AddRefed<nsIDOMStorage>
|
||||
nsDOMStorage::Clone()
|
||||
nsDOMStorage::Clone(nsIURI* aURI)
|
||||
{
|
||||
if (mUseDB) {
|
||||
if (UseDB()) {
|
||||
NS_ERROR("Uh, don't clone a global storage object.");
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsDOMStorage* storage = new nsDOMStorage(mDomain, PR_FALSE);
|
||||
nsDOMStorage* storage = new nsDOMStorage(aURI, mDomain, PR_FALSE);
|
||||
if (!storage)
|
||||
return nsnull;
|
||||
|
||||
|
@ -576,7 +649,7 @@ KeysArrayBuilder(nsSessionStorageEntry* aEntry, void* userArg)
|
|||
nsTArray<nsString> *
|
||||
nsDOMStorage::GetKeys()
|
||||
{
|
||||
if (mUseDB)
|
||||
if (UseDB())
|
||||
CacheKeysFromDB();
|
||||
|
||||
KeysArrayBuilderStruct keystruct;
|
||||
|
@ -603,7 +676,7 @@ nsDOMStorage::BroadcastChangeNotification()
|
|||
// domain, but if it's a global storage object we do.
|
||||
observerService->NotifyObservers((nsIDOMStorage *)this,
|
||||
"dom-storage-changed",
|
||||
mUseDB ? mDomain.get() : nsnull);
|
||||
UseDB() ? mDomain.get() : nsnull);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -623,6 +696,8 @@ nsresult
|
|||
nsDOMStorageList::NamedItem(const nsAString& aDomain,
|
||||
nsIDOMStorage** aStorage)
|
||||
{
|
||||
*aStorage = nsnull;
|
||||
|
||||
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
|
||||
if (!ssm)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -631,23 +706,27 @@ nsDOMStorageList::NamedItem(const nsAString& aDomain,
|
|||
nsresult rv = ssm->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> systemPrincipal;
|
||||
rv = ssm->GetSystemPrincipal(getter_AddRefs(systemPrincipal));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsCAutoString currentDomain;
|
||||
if (subjectPrincipal) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = subjectPrincipal->GetURI(getter_AddRefs(uri));
|
||||
if (NS_SUCCEEDED(rv) && uri) {
|
||||
PRPackedBool sessionOnly;
|
||||
if (!nsDOMStorage::CanUseStorage(uri, &sessionOnly))
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
|
||||
rv = uri->GetAsciiHost(currentDomain);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_SECURITY_ERR);
|
||||
}
|
||||
}
|
||||
|
||||
if (subjectPrincipal == systemPrincipal || !currentDomain.IsEmpty()) {
|
||||
return GetStorageForDomain(aDomain, NS_ConvertUTF8toUTF16(currentDomain),
|
||||
subjectPrincipal == systemPrincipal, aStorage);
|
||||
PRBool isSystem;
|
||||
rv = ssm->SubjectPrincipalIsSystem(&isSystem);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (isSystem || !currentDomain.IsEmpty()) {
|
||||
return GetStorageForDomain(uri, aDomain, NS_ConvertUTF8toUTF16(currentDomain),
|
||||
isSystem, aStorage);
|
||||
}
|
||||
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
|
@ -690,11 +769,20 @@ nsDOMStorageList::CanAccessDomain(const nsAString& aRequestedDomain,
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsDOMStorageList::GetStorageForDomain(const nsAString& aRequestedDomain,
|
||||
nsDOMStorageList::GetStorageForDomain(nsIURI* aURI,
|
||||
const nsAString& aRequestedDomain,
|
||||
const nsAString& aCurrentDomain,
|
||||
PRBool aNoCurrentDomainCheck,
|
||||
nsIDOMStorage** aStorage)
|
||||
{
|
||||
// fail if the domain contains no periods.
|
||||
// XXXndeakin update this when bug 342314 is fixed so that we can check
|
||||
// for top-level domain names properly
|
||||
nsAutoString trimmedDomain(aRequestedDomain);
|
||||
trimmedDomain.Trim(".");
|
||||
if (trimmedDomain.FindChar('.') == kNotFound)
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
|
||||
if (!aNoCurrentDomainCheck && !CanAccessDomain(aRequestedDomain,
|
||||
aCurrentDomain)) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
|
@ -717,7 +805,7 @@ nsDOMStorageList::GetStorageForDomain(const nsAString& aRequestedDomain,
|
|||
|
||||
// now have a valid domain, so look it up in the storage table
|
||||
if (!mStorages.Get(usedDomain, aStorage)) {
|
||||
nsCOMPtr<nsIDOMStorage> newstorage = new nsDOMStorage(usedDomain, PR_TRUE);
|
||||
nsCOMPtr<nsIDOMStorage> newstorage = new nsDOMStorage(aURI, usedDomain, PR_TRUE);
|
||||
if (!newstorage)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
|
@ -788,9 +876,11 @@ NS_IMPL_RELEASE(nsDOMStorageItem)
|
|||
|
||||
nsDOMStorageItem::nsDOMStorageItem(nsDOMStorage* aStorage,
|
||||
const nsAString& aKey,
|
||||
const nsAString& aValue,
|
||||
PRBool aSecure)
|
||||
: mSecure(aSecure),
|
||||
mKeyOrValue(aKey),
|
||||
mKey(aKey),
|
||||
mValue(aValue),
|
||||
mStorage(aStorage)
|
||||
{
|
||||
}
|
||||
|
@ -802,13 +892,13 @@ nsDOMStorageItem::~nsDOMStorageItem()
|
|||
NS_IMETHODIMP
|
||||
nsDOMStorageItem::GetSecure(PRBool* aSecure)
|
||||
{
|
||||
if (!IsCallerSecure()) {
|
||||
if (!mStorage->CacheStoragePermissions() || !IsCallerSecure()) {
|
||||
return NS_ERROR_DOM_INVALID_ACCESS_ERR;
|
||||
}
|
||||
|
||||
if (mStorage) {
|
||||
if (mStorage->UseDB()) {
|
||||
nsAutoString value;
|
||||
return mStorage->GetDBValue(mKeyOrValue, value, aSecure);
|
||||
return mStorage->GetDBValue(mKey, value, aSecure);
|
||||
}
|
||||
|
||||
*aSecure = IsSecure();
|
||||
|
@ -818,12 +908,12 @@ nsDOMStorageItem::GetSecure(PRBool* aSecure)
|
|||
NS_IMETHODIMP
|
||||
nsDOMStorageItem::SetSecure(PRBool aSecure)
|
||||
{
|
||||
if (!IsCallerSecure()) {
|
||||
if (!mStorage->CacheStoragePermissions() || !IsCallerSecure()) {
|
||||
return NS_ERROR_DOM_INVALID_ACCESS_ERR;
|
||||
}
|
||||
|
||||
if (mStorage) {
|
||||
nsresult rv = mStorage->SetSecure(mKeyOrValue, aSecure);
|
||||
if (mStorage->UseDB()) {
|
||||
nsresult rv = mStorage->SetSecure(mKey, aSecure);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
@ -834,10 +924,13 @@ nsDOMStorageItem::SetSecure(PRBool aSecure)
|
|||
NS_IMETHODIMP
|
||||
nsDOMStorageItem::GetValue(nsAString& aValue)
|
||||
{
|
||||
if (mStorage) {
|
||||
if (!mStorage->CacheStoragePermissions())
|
||||
return NS_ERROR_DOM_INVALID_ACCESS_ERR;
|
||||
|
||||
if (mStorage->UseDB()) {
|
||||
// GetDBValue checks the secure state so no need to do it here
|
||||
PRBool secure;
|
||||
nsresult rv = mStorage->GetDBValue(mKeyOrValue, aValue, &secure);
|
||||
nsresult rv = mStorage->GetDBValue(mKey, aValue, &secure);
|
||||
return (rv == NS_ERROR_DOM_NOT_FOUND_ERR) ? NS_OK : rv;
|
||||
}
|
||||
|
||||
|
@ -845,29 +938,31 @@ nsDOMStorageItem::GetValue(nsAString& aValue)
|
|||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
aValue = mKeyOrValue;
|
||||
aValue = mValue;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMStorageItem::SetValue(const nsAString& aValue)
|
||||
{
|
||||
if (!mStorage->CacheStoragePermissions())
|
||||
return NS_ERROR_DOM_INVALID_ACCESS_ERR;
|
||||
|
||||
PRBool secureCaller = IsCallerSecure();
|
||||
|
||||
if (mStorage) {
|
||||
if (mStorage->UseDB()) {
|
||||
// SetDBValue() does the security checks for us.
|
||||
return mStorage->SetDBValue(mKeyOrValue, aValue, secureCaller);
|
||||
return mStorage->SetDBValue(mKey, aValue, secureCaller);
|
||||
}
|
||||
|
||||
PRBool secureItem = IsSecure();
|
||||
|
||||
if (!secureCaller && secureItem) {
|
||||
// The item is secure, but the caller isn't. Throw.
|
||||
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
mKeyOrValue = aValue;
|
||||
mValue = aValue;
|
||||
mSecure = secureCaller;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ class nsDOMStorage : public nsIDOMStorage,
|
|||
{
|
||||
public:
|
||||
nsDOMStorage();
|
||||
nsDOMStorage(const nsAString& aDomain, PRBool aUseDB);
|
||||
nsDOMStorage(nsIURI* aURI, const nsAString& aDomain, PRBool aUseDB);
|
||||
virtual ~nsDOMStorage();
|
||||
|
||||
// nsISupports
|
||||
|
@ -83,13 +83,23 @@ public:
|
|||
NS_DECL_NSIDOMSTORAGE
|
||||
|
||||
// nsPIDOMStorage
|
||||
virtual void Init(const nsAString& aDomain, PRBool aUseDB);
|
||||
virtual already_AddRefed<nsIDOMStorage> Clone();
|
||||
virtual void Init(nsIURI* aURI, const nsAString& aDomain, PRBool aUseDB);
|
||||
virtual already_AddRefed<nsIDOMStorage> Clone(nsIURI* aURI);
|
||||
virtual nsTArray<nsString> *GetKeys();
|
||||
|
||||
// cache the keys from the database for faster lookup
|
||||
nsresult
|
||||
CacheKeysFromDB();
|
||||
PRBool UseDB() { return mUseDB && !mSessionOnly; }
|
||||
|
||||
// cache whether storage may be used by aURI, and whether it is session
|
||||
// only. If aURI is null, the uri associated with this storage (mURI)
|
||||
// is checked. Returns true if storage may be used.
|
||||
static PRBool
|
||||
CanUseStorage(nsIURI* aURI, PRPackedBool* aSessionOnly);
|
||||
|
||||
PRBool
|
||||
CacheStoragePermissions()
|
||||
{
|
||||
return CanUseStorage(mURI, &mSessionOnly);
|
||||
}
|
||||
|
||||
// retrieve the value and secure state corresponding to a key out of storage.
|
||||
nsresult
|
||||
|
@ -111,13 +121,22 @@ protected:
|
|||
|
||||
nsresult InitDB();
|
||||
|
||||
// cache the keys from the database for faster lookup
|
||||
nsresult CacheKeysFromDB();
|
||||
|
||||
void BroadcastChangeNotification();
|
||||
|
||||
// true if the storage database should be used for values
|
||||
PRBool mUseDB;
|
||||
PRPackedBool mUseDB;
|
||||
|
||||
// true if the preferences indicates that this storage should be session only
|
||||
PRPackedBool mSessionOnly;
|
||||
|
||||
// true if items from the database are cached
|
||||
PRBool mItemsCached;
|
||||
PRPackedBool mItemsCached;
|
||||
|
||||
// the URI this store is associated with
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
|
||||
// domain this store is associated with
|
||||
nsAutoString mDomain;
|
||||
|
@ -146,6 +165,15 @@ public:
|
|||
// nsIDOMStorageList
|
||||
NS_DECL_NSIDOMSTORAGELIST
|
||||
|
||||
/**
|
||||
* Check whether aCurrentDomain has access to aRequestedDomain
|
||||
*/
|
||||
static PRBool
|
||||
CanAccessDomain(const nsAString& aRequestedDomain,
|
||||
const nsAString& aCurrentDomain);
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Return the global nsIDOMStorage for a particular domain.
|
||||
* aNoCurrentDomainCheck may be true to skip the domain comparison;
|
||||
|
@ -157,7 +185,8 @@ public:
|
|||
* @param aNoCurrentDomainCheck true to skip domain comparison
|
||||
*/
|
||||
nsresult
|
||||
GetStorageForDomain(const nsAString& aRequestedDomain,
|
||||
GetStorageForDomain(nsIURI* aURI,
|
||||
const nsAString& aRequestedDomain,
|
||||
const nsAString& aCurrentDomain,
|
||||
PRBool aNoCurrentDomainCheck,
|
||||
nsIDOMStorage** aStorage);
|
||||
|
@ -169,15 +198,6 @@ public:
|
|||
ConvertDomainToArray(const nsAString& aDomain,
|
||||
nsStringArray* aArray);
|
||||
|
||||
/**
|
||||
* Check whether aCurrentDomain has access to aRequestedDomain
|
||||
*/
|
||||
static PRBool
|
||||
CanAccessDomain(const nsAString& aRequestedDomain,
|
||||
const nsAString& aCurrentDomain);
|
||||
|
||||
protected:
|
||||
|
||||
nsInterfaceHashtable<nsStringHashKey, nsIDOMStorage> mStorages;
|
||||
};
|
||||
|
||||
|
@ -187,6 +207,7 @@ class nsDOMStorageItem : public nsIDOMStorageItem,
|
|||
public:
|
||||
nsDOMStorageItem(nsDOMStorage* aStorage,
|
||||
const nsAString& aKey,
|
||||
const nsAString& aValue,
|
||||
PRBool aSecure);
|
||||
virtual ~nsDOMStorageItem();
|
||||
|
||||
|
@ -211,16 +232,17 @@ public:
|
|||
|
||||
const nsAString& GetValueInternal()
|
||||
{
|
||||
NS_ASSERTION(!mStorage, "Don't call this on global storage items!");
|
||||
return mValue;
|
||||
}
|
||||
|
||||
return mKeyOrValue;
|
||||
const void SetValueInternal(const nsAString& aValue)
|
||||
{
|
||||
mValue = aValue;
|
||||
}
|
||||
|
||||
void ClearValue()
|
||||
{
|
||||
NS_ASSERTION(!mStorage, "Don't call this on global storage items!");
|
||||
|
||||
mKeyOrValue.Truncate();
|
||||
mValue.Truncate();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -228,8 +250,11 @@ protected:
|
|||
// true if this value is for secure sites only
|
||||
PRBool mSecure;
|
||||
|
||||
// value of the item, or key for the item if it came from the db.
|
||||
nsString mKeyOrValue;
|
||||
// key for the item
|
||||
nsString mKey;
|
||||
|
||||
// value of the item
|
||||
nsString mValue;
|
||||
|
||||
// If this item came from the db, mStorage points to the storage
|
||||
// object where this item came from.
|
||||
|
|
|
@ -159,7 +159,7 @@ nsDOMStorageDB::GetAllKeys(const nsAString& aDomain,
|
|||
nsSessionStorageEntry* entry = aKeys->PutEntry(key);
|
||||
NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
entry->mItem = new nsDOMStorageItem(aStorage, key, secureInt);
|
||||
entry->mItem = new nsDOMStorageItem(aStorage, key, EmptyString(), secureInt);
|
||||
if (!entry->mItem) {
|
||||
aKeys->RawRemoveEntry(entry);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
|
|
@ -452,6 +452,8 @@ pref("dom.popup_maximum", 20);
|
|||
pref("dom.popup_allowed_events", "change click dblclick mouseup reset submit");
|
||||
pref("dom.disable_open_click_delay", 1000);
|
||||
|
||||
pref("dom.storage.enabled", true);
|
||||
|
||||
// Disable popups from plugins by default
|
||||
// 0 = openAllowed
|
||||
// 1 = openControlled
|
||||
|
|
Загрузка…
Ссылка в новой задаче