зеркало из https://github.com/mozilla/pjs.git
Bug 458091: Don't store an mURI in nsDOMStorage. r=bz
This commit is contained in:
Родитель
7b0cf8b9ac
Коммит
f3c17be4a6
|
@ -437,6 +437,7 @@ NS_INTERFACE_MAP_BEGIN(nsDocShell)
|
|||
NS_INTERFACE_MAP_ENTRY(nsIAuthPromptProvider)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsILoadContext)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDocShell_MOZILLA_1_9_1)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDocLoader)
|
||||
|
||||
///*****************************************************************************
|
||||
|
@ -1684,14 +1685,68 @@ nsDocShell::HistoryPurged(PRInt32 aNumEntries)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::GetSessionStorageForPrincipal(nsIPrincipal* aPrincipal,
|
||||
PRBool aCreate,
|
||||
nsIDOMStorage** aStorage)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aStorage);
|
||||
*aStorage = nsnull;
|
||||
|
||||
if (!aPrincipal)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIURI> codebaseURI;
|
||||
nsresult rv = aPrincipal->GetDomain(getter_AddRefs(codebaseURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!codebaseURI) {
|
||||
rv = aPrincipal->GetURI(getter_AddRefs(codebaseURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (!codebaseURI)
|
||||
return NS_OK;
|
||||
|
||||
rv = GetSessionStorageForURI(codebaseURI, aCreate, aStorage);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsPIDOMStorage> piStorage = do_QueryInterface(*aStorage);
|
||||
if (piStorage) {
|
||||
PRBool canAccess = piStorage->CanAccess(aPrincipal);
|
||||
NS_ASSERTION(canAccess,
|
||||
"GetSessionStorageForPrincipal got a storage "
|
||||
"that could not be accessed!");
|
||||
if (!canAccess) {
|
||||
NS_RELEASE(*aStorage);
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::GetSessionStorageForURI(nsIURI* aURI,
|
||||
nsIDOMStorage** aStorage)
|
||||
{
|
||||
return GetSessionStorageForURI(aURI, PR_TRUE, aStorage);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocShell::GetSessionStorageForURI(nsIURI* aURI,
|
||||
PRBool aCreate,
|
||||
nsIDOMStorage** aStorage)
|
||||
{
|
||||
NS_ENSURE_ARG(aURI);
|
||||
NS_ENSURE_ARG_POINTER(aStorage);
|
||||
|
||||
*aStorage = nsnull;
|
||||
|
||||
nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(aURI);
|
||||
NS_ASSERTION(innerURI, "Failed to get innermost URI");
|
||||
if (!innerURI)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> topItem;
|
||||
nsresult rv = GetSameTypeRootTreeItem(getter_AddRefs(topItem));
|
||||
if (NS_FAILED(rv))
|
||||
|
@ -1700,18 +1755,18 @@ nsDocShell::GetSessionStorageForURI(nsIURI* aURI,
|
|||
if (!topItem)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDocShell> topDocShell = do_QueryInterface(topItem);
|
||||
nsDocShell* topDocShell = static_cast<nsDocShell*>(topItem.get());
|
||||
if (topDocShell != this)
|
||||
return topDocShell->GetSessionStorageForURI(aURI, aStorage);
|
||||
return topDocShell->GetSessionStorageForURI(aURI, aCreate, aStorage);
|
||||
|
||||
nsCAutoString currentDomain;
|
||||
rv = aURI->GetAsciiHost(currentDomain);
|
||||
rv = innerURI->GetAsciiHost(currentDomain);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (currentDomain.IsEmpty())
|
||||
return NS_OK;
|
||||
|
||||
if (!mStorages.Get(currentDomain, aStorage)) {
|
||||
if (!mStorages.Get(currentDomain, aStorage) && aCreate) {
|
||||
nsCOMPtr<nsIDOMStorage> newstorage =
|
||||
do_CreateInstance("@mozilla.org/dom/storage;1");
|
||||
if (!newstorage)
|
||||
|
@ -1720,13 +1775,12 @@ nsDocShell::GetSessionStorageForURI(nsIURI* aURI,
|
|||
nsCOMPtr<nsPIDOMStorage> pistorage = do_QueryInterface(newstorage);
|
||||
if (!pistorage)
|
||||
return NS_ERROR_FAILURE;
|
||||
pistorage->Init(aURI, NS_ConvertUTF8toUTF16(currentDomain), PR_FALSE);
|
||||
pistorage->Init(NS_ConvertUTF8toUTF16(currentDomain), PR_FALSE);
|
||||
|
||||
if (!mStorages.Put(currentDomain, newstorage))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
*aStorage = newstorage;
|
||||
NS_ADDREF(*aStorage);
|
||||
|
||||
newstorage.swap(*aStorage);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -1749,6 +1803,10 @@ nsDocShell::AddSessionStorage(const nsACString& aDomain,
|
|||
if (topItem) {
|
||||
nsCOMPtr<nsIDocShell> topDocShell = do_QueryInterface(topItem);
|
||||
if (topDocShell == this) {
|
||||
// Do not replace an existing session storage.
|
||||
if (mStorages.GetWeak(aDomain))
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
if (!mStorages.Put(aDomain, aStorage))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -6879,42 +6937,8 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
|||
|
||||
nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(newWin);
|
||||
targetDocShell = do_QueryInterface(webNav);
|
||||
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> sop =
|
||||
do_QueryInterface(mScriptGlobal);
|
||||
nsCOMPtr<nsIURI> currentCodebase;
|
||||
|
||||
if (sop) {
|
||||
nsIPrincipal *principal = sop->GetPrincipal();
|
||||
|
||||
if (principal) {
|
||||
principal->GetURI(getter_AddRefs(currentCodebase));
|
||||
}
|
||||
}
|
||||
|
||||
// We opened a new window for the target, clone the
|
||||
// session storage if the current URI's domain matches
|
||||
// that of the loading URI.
|
||||
if (targetDocShell && currentCodebase && aURI) {
|
||||
nsCAutoString thisDomain, newDomain;
|
||||
nsresult gethostrv = currentCodebase->GetAsciiHost(thisDomain);
|
||||
gethostrv |= aURI->GetAsciiHost(newDomain);
|
||||
if (NS_SUCCEEDED(gethostrv) && thisDomain.Equals(newDomain)) {
|
||||
nsCOMPtr<nsIDOMStorage> storage;
|
||||
GetSessionStorageForURI(currentCodebase,
|
||||
getter_AddRefs(storage));
|
||||
nsCOMPtr<nsPIDOMStorage> piStorage =
|
||||
do_QueryInterface(storage);
|
||||
if (piStorage) {
|
||||
nsCOMPtr<nsIDOMStorage> newstorage =
|
||||
piStorage->Clone(currentCodebase);
|
||||
targetDocShell->AddSessionStorage(thisDomain,
|
||||
newstorage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Transfer the load to the target DocShell... Pass nsnull as the
|
||||
// window target name from to prevent recursive retargeting!
|
||||
|
|
|
@ -187,7 +187,8 @@ class nsDocShell : public nsDocLoader,
|
|||
public nsIWebPageDescriptor,
|
||||
public nsIAuthPromptProvider,
|
||||
public nsIObserver,
|
||||
public nsILoadContext
|
||||
public nsILoadContext,
|
||||
public nsIDocShell_MOZILLA_1_9_1
|
||||
{
|
||||
friend class nsDSURIContentListener;
|
||||
|
||||
|
@ -217,6 +218,7 @@ public:
|
|||
NS_DECL_NSIAUTHPROMPTPROVIDER
|
||||
NS_DECL_NSIOBSERVER
|
||||
NS_DECL_NSILOADCONTEXT
|
||||
NS_DECL_NSIDOCSHELL_MOZILLA_1_9_1
|
||||
|
||||
NS_IMETHOD Stop() {
|
||||
// Need this here because otherwise nsIWebNavigation::Stop
|
||||
|
@ -549,6 +551,9 @@ protected:
|
|||
void ReattachEditorToWindow(nsISHEntry *aSHEntry);
|
||||
void DetachEditorFromWindow(nsISHEntry *aSHEntry);
|
||||
|
||||
nsresult GetSessionStorageForURI(nsIURI* aURI,
|
||||
PRBool create,
|
||||
nsIDOMStorage** aStorage);
|
||||
protected:
|
||||
// Override the parent setter from nsDocLoader
|
||||
virtual nsresult SetDocLoaderParent(nsDocLoader * aLoader);
|
||||
|
|
|
@ -67,6 +67,7 @@ interface nsISHEntry;
|
|||
interface nsILayoutHistoryState;
|
||||
interface nsISecureBrowserUI;
|
||||
interface nsIDOMStorage;
|
||||
interface nsIPrincipal;
|
||||
|
||||
[scriptable, uuid(dc4daea1-b43d-406f-bd62-c2ee879192ad)]
|
||||
interface nsIDocShell : nsISupports
|
||||
|
@ -423,7 +424,7 @@ interface nsIDocShell : nsISupports
|
|||
* Retrieves the WebApps session storage object for the supplied domain.
|
||||
* If it doesn't already exist, a new one will be created.
|
||||
*
|
||||
* @param domain the domain of the storage object to retrieve
|
||||
* @param uri the uri of the storage object to retrieve
|
||||
*/
|
||||
nsIDOMStorage getSessionStorageForURI(in nsIURI uri);
|
||||
|
||||
|
@ -475,3 +476,16 @@ interface nsIDocShell : nsISupports
|
|||
attribute boolean isOffScreenBrowser;
|
||||
};
|
||||
|
||||
[scriptable, uuid(460ba822-e664-4c38-9b08-98d2736473d7)]
|
||||
interface nsIDocShell_MOZILLA_1_9_1 : nsISupports
|
||||
{
|
||||
/*
|
||||
* Retrieves the WebApps session storage object for the supplied principal.
|
||||
*
|
||||
* @param principal returns a storage for this principal
|
||||
* @param create If true and a session storage object doesn't
|
||||
* already exist, a new one will be created.
|
||||
*/
|
||||
nsIDOMStorage getSessionStorageForPrincipal(in nsIPrincipal principal,
|
||||
in boolean create);
|
||||
};
|
||||
|
|
|
@ -45,21 +45,25 @@
|
|||
|
||||
class nsIDOMStorage;
|
||||
class nsIURI;
|
||||
class nsIPrincipal;
|
||||
|
||||
#define NS_PIDOMSTORAGE_IID \
|
||||
{ 0x2fdbb82e, 0x4b47, 0x406a, \
|
||||
{ 0xb1, 0x17, 0x6d, 0x67, 0x58, 0xc1, 0xee, 0x6b } }
|
||||
{ 0x2cbaea60, 0x69e7, 0x4b49, \
|
||||
{ 0xa2, 0xe2, 0x99, 0x53, 0xf4, 0x11, 0xd0, 0x8f } }
|
||||
|
||||
class nsPIDOMStorage : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_PIDOMSTORAGE_IID)
|
||||
|
||||
virtual void Init(nsIURI* aURI, const nsAString &aDomain, PRBool aUseDB) = 0;
|
||||
virtual void Init(const nsAString &aDomain, PRBool aUseDB) = 0;
|
||||
|
||||
virtual already_AddRefed<nsIDOMStorage> Clone(nsIURI* aURI) = 0;
|
||||
virtual already_AddRefed<nsIDOMStorage> Clone() = 0;
|
||||
|
||||
virtual nsTArray<nsString> *GetKeys() = 0;
|
||||
|
||||
virtual const nsString &Domain() = 0;
|
||||
virtual PRBool CanAccess(nsIPrincipal *aPrincipal) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsPIDOMStorage, NS_PIDOMSTORAGE_IID)
|
||||
|
|
|
@ -6693,20 +6693,23 @@ nsGlobalWindow::GetSessionStorage(nsIDOMStorage ** aSessionStorage)
|
|||
*aSessionStorage = nsnull;
|
||||
|
||||
nsIPrincipal *principal = GetPrincipal();
|
||||
nsIDocShell *docShell = GetDocShell();
|
||||
nsCOMPtr<nsIDocShell_MOZILLA_1_9_1> docShell =
|
||||
do_QueryInterface(GetDocShell());
|
||||
|
||||
if (!principal || !docShell) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> codebase;
|
||||
nsresult rv = principal->GetURI(getter_AddRefs(codebase));
|
||||
nsresult rv = docShell->GetSessionStorageForPrincipal(principal,
|
||||
PR_TRUE,
|
||||
aSessionStorage);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (NS_FAILED(rv) || !codebase) {
|
||||
return NS_FAILED(rv) ? rv : NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
||||
if (!*aSessionStorage) {
|
||||
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
||||
}
|
||||
|
||||
return docShell->GetSessionStorageForURI(codebase, aSessionStorage);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -6863,16 +6866,23 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
nsIPrincipal *principal;
|
||||
nsresult rv;
|
||||
|
||||
principal = GetPrincipal();
|
||||
if (!aData) {
|
||||
nsCOMPtr<nsIDOMStorage> storage;
|
||||
GetSessionStorage(getter_AddRefs(storage));
|
||||
nsCOMPtr<nsIDocShell_MOZILLA_1_9_1> docShell =
|
||||
do_QueryInterface(GetDocShell());
|
||||
if (principal && docShell) {
|
||||
nsCOMPtr<nsIDOMStorage> storage;
|
||||
docShell->GetSessionStorageForPrincipal(principal,
|
||||
PR_FALSE,
|
||||
getter_AddRefs(storage));
|
||||
|
||||
if (storage != aSubject && !aData) {
|
||||
// A sessionStorage object changed, but not our session storage
|
||||
// object.
|
||||
return NS_OK;
|
||||
if (storage != aSubject) {
|
||||
// A sessionStorage object changed, but not our session storage
|
||||
// object.
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
} else if ((principal = GetPrincipal())) {
|
||||
} else if (principal) {
|
||||
// A global storage object changed, check to see if it's one
|
||||
// this window can access.
|
||||
|
||||
|
@ -7088,12 +7098,6 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
|
|||
const PRBool checkForPopup =
|
||||
!aDialog && !WindowExists(aName, !aCalledNoScript);
|
||||
|
||||
nsCOMPtr<nsIURI> currentCodebase;
|
||||
|
||||
if (aCalleePrincipal) {
|
||||
aCalleePrincipal->GetURI(getter_AddRefs(currentCodebase));
|
||||
}
|
||||
|
||||
// Note: it's very important that this be an nsXPIDLCString, since we want
|
||||
// .get() on it to return nsnull until we write stuff to it. The window
|
||||
// watcher expects a null URL string if there is no URL to load.
|
||||
|
@ -7239,38 +7243,6 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
|
|||
FireAbuseEvents(PR_FALSE, PR_TRUE, aUrl, aName, aOptions);
|
||||
}
|
||||
|
||||
// copy the session storage data over to the new window if
|
||||
// necessary. If the new window has the same domain as this window
|
||||
// did at the beginning of this function, the session storage data
|
||||
// for that domain, and only that domain, is copied over.
|
||||
nsGlobalWindow *opened = static_cast<nsGlobalWindow *>(*aReturn);
|
||||
nsIDocShell* newDocShell = opened->GetDocShell();
|
||||
|
||||
if (currentCodebase && newDocShell && mDocShell && url.get()) {
|
||||
nsCOMPtr<nsIURI> newURI;
|
||||
|
||||
JSContext *cx;
|
||||
PRBool freePass;
|
||||
BuildURIfromBase(url, getter_AddRefs(newURI), &freePass, &cx);
|
||||
|
||||
if (newURI) {
|
||||
nsCAutoString thisDomain, newDomain;
|
||||
nsresult gethostrv = currentCodebase->GetAsciiHost(thisDomain);
|
||||
gethostrv |= newURI->GetAsciiHost(newDomain);
|
||||
|
||||
if (NS_SUCCEEDED(gethostrv) && thisDomain.Equals(newDomain)) {
|
||||
nsCOMPtr<nsIDOMStorage> storage;
|
||||
mDocShell->GetSessionStorageForURI(currentCodebase,
|
||||
getter_AddRefs(storage));
|
||||
nsCOMPtr<nsPIDOMStorage> piStorage = do_QueryInterface(storage);
|
||||
if (piStorage) {
|
||||
nsCOMPtr<nsIDOMStorage> newstorage = piStorage->Clone(newURI);
|
||||
newDocShell->AddSessionStorage(thisDomain, newstorage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -78,6 +78,40 @@ static const char kCookiesLifetimePolicy[] = "network.cookie.lifetimePolicy";
|
|||
static const char kOfflineAppWarnQuota[] = "offline-apps.quota.warn";
|
||||
static const char kOfflineAppQuota[] = "offline-apps.quota.max";
|
||||
|
||||
// The URI returned is the innermost URI that should be used for
|
||||
// security-check-like stuff. aHost is its hostname, correctly canonicalized.
|
||||
static nsresult
|
||||
GetPrincipalURIAndHost(nsIPrincipal* aPrincipal, nsIURI** aURI, nsString& aHost)
|
||||
{
|
||||
nsresult rv = aPrincipal->GetDomain(aURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!*aURI) {
|
||||
rv = aPrincipal->GetURI(aURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (!*aURI) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(*aURI);
|
||||
if (!innerURI) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
nsCAutoString asciiHost;
|
||||
rv = innerURI->GetAsciiHost(asciiHost);
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
CopyUTF8toUTF16(asciiHost, aHost);
|
||||
innerURI.swap(*aURI);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//
|
||||
// Helper that tells us whether the caller is secure or not.
|
||||
//
|
||||
|
@ -375,11 +409,8 @@ SessionStorageTraverser(nsSessionStorageEntry* aEntry, void* userArg) {
|
|||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMStorage)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMStorage)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mURI)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsDOMStorage)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMStorage)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mURI)
|
||||
{
|
||||
if (tmp->mItems.IsInitialized()) {
|
||||
tmp->mItems.EnumerateEntries(SessionStorageTraverser, &cb);
|
||||
|
@ -417,11 +448,10 @@ nsDOMStorage::nsDOMStorage()
|
|||
nsDOMStorageManager::gStorageManager->AddToStoragesHash(this);
|
||||
}
|
||||
|
||||
nsDOMStorage::nsDOMStorage(nsIURI* aURI, const nsAString& aDomain, PRBool aUseDB)
|
||||
nsDOMStorage::nsDOMStorage(const nsAString& aDomain, PRBool aUseDB)
|
||||
: mUseDB(aUseDB),
|
||||
mSessionOnly(PR_TRUE),
|
||||
mItemsCached(PR_FALSE),
|
||||
mURI(aURI),
|
||||
mDomain(aDomain)
|
||||
{
|
||||
#ifndef MOZ_STORAGE
|
||||
|
@ -440,9 +470,8 @@ nsDOMStorage::~nsDOMStorage()
|
|||
}
|
||||
|
||||
void
|
||||
nsDOMStorage::Init(nsIURI* aURI, const nsAString& aDomain, PRBool aUseDB)
|
||||
nsDOMStorage::Init(const nsAString& aDomain, PRBool aUseDB)
|
||||
{
|
||||
mURI = aURI;
|
||||
mDomain.Assign(aDomain);
|
||||
#ifdef MOZ_STORAGE
|
||||
mUseDB = aUseDB;
|
||||
|
@ -453,10 +482,10 @@ nsDOMStorage::Init(nsIURI* aURI, const nsAString& aDomain, PRBool aUseDB)
|
|||
|
||||
//static
|
||||
PRBool
|
||||
nsDOMStorage::CanUseStorage(nsIURI* aURI, PRPackedBool* aSessionOnly)
|
||||
nsDOMStorage::CanUseStorage(PRPackedBool* aSessionOnly)
|
||||
{
|
||||
// check if the domain can use storage. Downgrade to session only if only
|
||||
// session storage may be used.
|
||||
// check if the calling domain can use storage. Downgrade to session
|
||||
// only if only session storage may be used.
|
||||
NS_ASSERTION(aSessionOnly, "null session flag");
|
||||
*aSessionOnly = PR_FALSE;
|
||||
|
||||
|
@ -467,13 +496,28 @@ nsDOMStorage::CanUseStorage(nsIURI* aURI, PRPackedBool* aSessionOnly)
|
|||
if (nsContentUtils::IsCallerChrome())
|
||||
return PR_TRUE;
|
||||
|
||||
nsCOMPtr<nsIPrincipal> subjectPrincipal;
|
||||
nsContentUtils::GetSecurityManager()->
|
||||
GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
|
||||
|
||||
// if subjectPrincipal were null we'd have returned after
|
||||
// IsCallerChrome().
|
||||
|
||||
nsCOMPtr<nsIURI> subjectURI;
|
||||
nsAutoString unused;
|
||||
if (NS_FAILED(GetPrincipalURIAndHost(subjectPrincipal,
|
||||
getter_AddRefs(subjectURI),
|
||||
unused))) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPermissionManager> permissionManager =
|
||||
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
|
||||
if (!permissionManager)
|
||||
return PR_FALSE;
|
||||
|
||||
PRUint32 perm;
|
||||
permissionManager->TestPermission(aURI, kPermissionType, &perm);
|
||||
permissionManager->TestPermission(subjectURI, kPermissionType, &perm);
|
||||
|
||||
if (perm == nsIPermissionManager::DENY_ACTION)
|
||||
return PR_FALSE;
|
||||
|
@ -496,6 +540,23 @@ nsDOMStorage::CanUseStorage(nsIURI* aURI, PRPackedBool* aSessionOnly)
|
|||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDOMStorage::CacheStoragePermissions()
|
||||
{
|
||||
if (!CanUseStorage(&mSessionOnly))
|
||||
return PR_FALSE;
|
||||
|
||||
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
|
||||
if (!ssm)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIPrincipal> subjectPrincipal;
|
||||
ssm->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
|
||||
|
||||
return CanAccess(subjectPrincipal);
|
||||
}
|
||||
|
||||
|
||||
class ItemCounterState
|
||||
{
|
||||
public:
|
||||
|
@ -833,40 +894,6 @@ nsDOMStorage::GetDBValue(const nsAString& aKey, nsAString& aValue,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// The URI returned is the innermost URI that should be used for
|
||||
// security-check-like stuff. aHost is its hostname, correctly canonicalized.
|
||||
static nsresult
|
||||
GetPrincipalURIAndHost(nsIPrincipal* aPrincipal, nsIURI** aURI, nsString& aHost)
|
||||
{
|
||||
nsresult rv = aPrincipal->GetDomain(aURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!*aURI) {
|
||||
rv = aPrincipal->GetURI(aURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (!*aURI) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(*aURI);
|
||||
if (!innerURI) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
nsCAutoString asciiHost;
|
||||
rv = innerURI->GetAsciiHost(asciiHost);
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
CopyUTF8toUTF16(asciiHost, aHost);
|
||||
innerURI.swap(*aURI);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMStorage::SetDBValue(const nsAString& aKey,
|
||||
const nsAString& aValue,
|
||||
|
@ -1000,7 +1027,7 @@ CopyStorageItems(nsSessionStorageEntry* aEntry, void* userArg)
|
|||
}
|
||||
|
||||
already_AddRefed<nsIDOMStorage>
|
||||
nsDOMStorage::Clone(nsIURI* aURI)
|
||||
nsDOMStorage::Clone()
|
||||
{
|
||||
if (UseDB()) {
|
||||
NS_ERROR("Uh, don't clone a global storage object.");
|
||||
|
@ -1008,7 +1035,7 @@ nsDOMStorage::Clone(nsIURI* aURI)
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
nsDOMStorage* storage = new nsDOMStorage(aURI, mDomain, PR_FALSE);
|
||||
nsDOMStorage* storage = new nsDOMStorage(mDomain, PR_FALSE);
|
||||
if (!storage)
|
||||
return nsnull;
|
||||
|
||||
|
@ -1051,6 +1078,36 @@ nsDOMStorage::GetKeys()
|
|||
return keystruct.keys;
|
||||
}
|
||||
|
||||
const nsString &
|
||||
nsDOMStorage::Domain()
|
||||
{
|
||||
return mDomain;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDOMStorage::CanAccess(nsIPrincipal *aPrincipal)
|
||||
{
|
||||
// Allow C++/system callers to access the storage
|
||||
if (!aPrincipal)
|
||||
return PR_TRUE;
|
||||
|
||||
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
|
||||
if (!ssm)
|
||||
return PR_TRUE;
|
||||
|
||||
PRBool isSystem;
|
||||
if (NS_SUCCEEDED(ssm->IsSystemPrincipal(aPrincipal, &isSystem) && isSystem))
|
||||
return PR_TRUE;
|
||||
|
||||
nsAutoString domain;
|
||||
nsCOMPtr<nsIURI> unused;
|
||||
nsresult rv = GetPrincipalURIAndHost(aPrincipal,
|
||||
getter_AddRefs(unused), domain);
|
||||
NS_ENSURE_SUCCESS(rv, PR_FALSE);
|
||||
|
||||
return domain.Equals(mDomain);
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMStorage::BroadcastChangeNotification()
|
||||
{
|
||||
|
@ -1111,31 +1168,28 @@ nsDOMStorageList::GetNamedItem(const nsAString& aDomain, nsresult* aResult)
|
|||
*aResult = ssm->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
|
||||
NS_ENSURE_SUCCESS(*aResult, nsnull);
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsAutoString currentDomain;
|
||||
if (subjectPrincipal) {
|
||||
*aResult = GetPrincipalURIAndHost(subjectPrincipal, getter_AddRefs(uri),
|
||||
nsCOMPtr<nsIURI> unused;
|
||||
*aResult = GetPrincipalURIAndHost(subjectPrincipal, getter_AddRefs(unused),
|
||||
currentDomain);
|
||||
NS_ENSURE_SUCCESS(*aResult, nsnull);
|
||||
|
||||
if (uri) {
|
||||
PRPackedBool sessionOnly;
|
||||
if (!nsDOMStorage::CanUseStorage(uri, &sessionOnly)) {
|
||||
*aResult = NS_ERROR_DOM_SECURITY_ERR;
|
||||
return nsnull;
|
||||
}
|
||||
PRPackedBool sessionOnly;
|
||||
if (!nsDOMStorage::CanUseStorage(&sessionOnly)) {
|
||||
*aResult = NS_ERROR_DOM_SECURITY_ERR;
|
||||
return nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
PRBool isSystem = nsContentUtils::IsCallerTrustedForRead();
|
||||
|
||||
if (isSystem || !currentDomain.IsEmpty()) {
|
||||
return GetStorageForDomain(uri, NS_ConvertUTF8toUTF16(requestedDomain),
|
||||
currentDomain, isSystem, aResult);
|
||||
if (currentDomain.IsEmpty() && !isSystem) {
|
||||
*aResult = NS_ERROR_DOM_SECURITY_ERR;
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
*aResult = NS_ERROR_DOM_SECURITY_ERR;
|
||||
return nsnull;
|
||||
return GetStorageForDomain(NS_ConvertUTF8toUTF16(requestedDomain),
|
||||
currentDomain, isSystem, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -1156,8 +1210,7 @@ nsDOMStorageList::CanAccessDomain(const nsAString& aRequestedDomain,
|
|||
}
|
||||
|
||||
nsIDOMStorage*
|
||||
nsDOMStorageList::GetStorageForDomain(nsIURI* aURI,
|
||||
const nsAString& aRequestedDomain,
|
||||
nsDOMStorageList::GetStorageForDomain(const nsAString& aRequestedDomain,
|
||||
const nsAString& aCurrentDomain,
|
||||
PRBool aNoCurrentDomainCheck,
|
||||
nsresult* aResult)
|
||||
|
@ -1186,7 +1239,7 @@ nsDOMStorageList::GetStorageForDomain(nsIURI* aURI,
|
|||
// now have a valid domain, so look it up in the storage table
|
||||
nsIDOMStorage* storage = mStorages.GetWeak(usedDomain);
|
||||
if (!storage) {
|
||||
nsCOMPtr<nsIDOMStorage> newstorage = new nsDOMStorage(aURI, usedDomain, PR_TRUE);
|
||||
nsCOMPtr<nsIDOMStorage> newstorage = new nsDOMStorage(usedDomain, PR_TRUE);
|
||||
if (newstorage && mStorages.Put(usedDomain, newstorage))
|
||||
storage = newstorage;
|
||||
else
|
||||
|
|
|
@ -116,7 +116,7 @@ class nsDOMStorage : public nsIDOMStorage,
|
|||
{
|
||||
public:
|
||||
nsDOMStorage();
|
||||
nsDOMStorage(nsIURI* aURI, const nsAString& aDomain, PRBool aUseDB);
|
||||
nsDOMStorage(const nsAString& aDomain, PRBool aUseDB);
|
||||
virtual ~nsDOMStorage();
|
||||
|
||||
// nsISupports
|
||||
|
@ -127,23 +127,29 @@ public:
|
|||
NS_DECL_NSIDOMSTORAGE
|
||||
|
||||
// nsPIDOMStorage
|
||||
virtual void Init(nsIURI* aURI, const nsAString& aDomain, PRBool aUseDB);
|
||||
virtual already_AddRefed<nsIDOMStorage> Clone(nsIURI* aURI);
|
||||
virtual void Init(const nsAString& aDomain, PRBool aUseDB);
|
||||
virtual already_AddRefed<nsIDOMStorage> Clone();
|
||||
virtual nsTArray<nsString> *GetKeys();
|
||||
virtual const nsString &Domain();
|
||||
virtual PRBool CanAccess(nsIPrincipal *aPrincipal);
|
||||
|
||||
// If true, the contents of the storage should be stored in the
|
||||
// database, otherwise this storage should act like a session
|
||||
// storage.
|
||||
// This call relies on mSessionOnly, and should only be used
|
||||
// after a CacheStoragePermissions() call. See the comments
|
||||
// for mSessionOnly below.
|
||||
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.
|
||||
// Check whether storage may be used by the caller, and whether it
|
||||
// is session only. Returns true if storage may be used.
|
||||
static PRBool
|
||||
CanUseStorage(nsIURI* aURI, PRPackedBool* aSessionOnly);
|
||||
CanUseStorage(PRPackedBool* aSessionOnly);
|
||||
|
||||
// Check whether storage may be used. Updates mSessionOnly based on
|
||||
// the result of CanUseStorage.
|
||||
PRBool
|
||||
CacheStoragePermissions()
|
||||
{
|
||||
return CanUseStorage(mURI, &mSessionOnly);
|
||||
}
|
||||
CacheStoragePermissions();
|
||||
|
||||
// retrieve the value and secure state corresponding to a key out of storage.
|
||||
nsresult
|
||||
|
@ -188,15 +194,16 @@ protected:
|
|||
// true if the storage database should be used for values
|
||||
PRPackedBool mUseDB;
|
||||
|
||||
// true if the preferences indicates that this storage should be session only
|
||||
// true if the preferences indicates that this storage should be
|
||||
// session only. This member is updated by
|
||||
// CacheStoragePermissions(), using the current principal.
|
||||
// CacheStoragePermissions() must be called at each entry point to
|
||||
// make sure this stays up to date.
|
||||
PRPackedBool mSessionOnly;
|
||||
|
||||
// true if items from the database are cached
|
||||
PRPackedBool mItemsCached;
|
||||
|
||||
// the URI this store is associated with
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
|
||||
// domain this store is associated with
|
||||
nsString mDomain;
|
||||
|
||||
|
@ -246,8 +253,7 @@ protected:
|
|||
* @param aNoCurrentDomainCheck true to skip domain comparison
|
||||
*/
|
||||
nsIDOMStorage*
|
||||
GetStorageForDomain(nsIURI* aURI,
|
||||
const nsAString& aRequestedDomain,
|
||||
GetStorageForDomain(const nsAString& aRequestedDomain,
|
||||
const nsAString& aCurrentDomain,
|
||||
PRBool aNoCurrentDomainCheck,
|
||||
nsresult* aResult);
|
||||
|
|
|
@ -84,6 +84,8 @@ _TEST_FILES = \
|
|||
test_bug440572.html \
|
||||
iframe_bug440572.html \
|
||||
test_bug437361.html \
|
||||
test_bug458091.html \
|
||||
bug458091_child.html \
|
||||
test_bug459848.html \
|
||||
test_bug465263.html \
|
||||
$(NULL)
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<html> <head>
|
||||
<title></title>
|
||||
<script type="text/javascript">
|
||||
function finish() {
|
||||
window.opener.finish(sessionStorage["testItem"]);
|
||||
window.close();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body onload="finish();">
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,101 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=458091
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 458091</title>
|
||||
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=458091">Mozilla Bug 458091</a>
|
||||
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<a id="testlink1" target="_blank" href="javascript:window.opener.finish(sessionStorage['testItem']);window.close();">Javascript Link</a>
|
||||
<a id="testlink2" target="_blank" href="bug458091_child.html">HTTP Link</a>
|
||||
<a id="testlink3" target="alreadyOpened" href="bug458091_child.html">Target Link</a>
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 458091 **/
|
||||
|
||||
var gTestWin;
|
||||
var gRunningTests = 0;
|
||||
|
||||
function runNextTest()
|
||||
{
|
||||
if (gTests.length > 0) {
|
||||
var test = gTests.shift();
|
||||
test();
|
||||
} else {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
function finish(val)
|
||||
{
|
||||
is(val, "correct value",
|
||||
"New window should access the correct session storage");
|
||||
if (--gRunningTests == 0) {
|
||||
runNextTest();
|
||||
}
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function test1() {
|
||||
sessionStorage["testItem"] = "correct value";
|
||||
|
||||
gRunningTests++;
|
||||
window.open('javascript:window.opener.finish(sessionStorage["testItem"]);window.close();');
|
||||
|
||||
gRunningTests++;
|
||||
window.open("bug458091_child.html");
|
||||
|
||||
gRunningTests++;
|
||||
sendMouseEvent({type: "click"}, "testlink1");
|
||||
|
||||
gRunningTests++;
|
||||
sendMouseEvent({type: "click"}, "testlink2");
|
||||
|
||||
// targetted load into an existing window
|
||||
var testWin = window.open("about:blank", "alreadyOpened");
|
||||
gRunningTests++;
|
||||
sendMouseEvent({type: "click"}, "testlink3");
|
||||
|
||||
// window.location into an existing window. Leave the window open
|
||||
// for further tests...
|
||||
gRunningTests++;
|
||||
gTestWin = window.open("about:blank", "testWindow");
|
||||
gTestWin.location = 'javascript:window.opener.finish(sessionStorage["testItem"]);';
|
||||
}
|
||||
|
||||
function test2() {
|
||||
// Now change session storage and load a new item in gTestWin, to
|
||||
// verify that they properly diverged after window.open().
|
||||
gRunningTests++;
|
||||
sessionStorage["testItem"] = "incorrect value";
|
||||
gTestWin.location = 'javascript:window.opener.finish(sessionStorage["testItem"]);';
|
||||
}
|
||||
|
||||
function test3()
|
||||
{
|
||||
// Now, with session storage still changed, try the window.open()
|
||||
// path, make sure it doesn't overwrite the session storage.
|
||||
gRunningTests++;
|
||||
window.open('javascript:window.opener.finish(sessionStorage["testItem"]);window.close();',
|
||||
"testWindow");
|
||||
}
|
||||
|
||||
var gTests = [test1, test2, test3];
|
||||
runNextTest();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -85,6 +85,8 @@
|
|||
#include "nsIMutableArray.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsIDeviceContext.h"
|
||||
#include "nsIDOMStorage.h"
|
||||
#include "nsPIDOMStorage.h"
|
||||
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsIPrefService.h"
|
||||
|
@ -919,6 +921,26 @@ nsWindowWatcher::OpenWindowJSInternal(nsIDOMWindow *aParent,
|
|||
nsIWebNavigation::LOAD_FLAGS_NONE, PR_TRUE);
|
||||
}
|
||||
|
||||
// Copy the current session storage for the current domain.
|
||||
nsCOMPtr<nsPIDOMWindow> piWindow = do_QueryInterface(aParent);
|
||||
nsCOMPtr<nsIDocShell_MOZILLA_1_9_1> parentDocShell;
|
||||
if (piWindow)
|
||||
parentDocShell = do_QueryInterface(piWindow->GetDocShell());
|
||||
|
||||
if (subjectPrincipal && parentDocShell) {
|
||||
nsCOMPtr<nsIDOMStorage> storage;
|
||||
parentDocShell->GetSessionStorageForPrincipal(subjectPrincipal, PR_FALSE,
|
||||
getter_AddRefs(storage));
|
||||
nsCOMPtr<nsPIDOMStorage> piStorage =
|
||||
do_QueryInterface(storage);
|
||||
if (piStorage){
|
||||
storage = piStorage->Clone();
|
||||
newDocShell->AddSessionStorage(
|
||||
NS_ConvertUTF16toUTF8(piStorage->Domain()),
|
||||
storage);
|
||||
}
|
||||
}
|
||||
|
||||
if (isNewToplevelWindow)
|
||||
SizeOpenedDocShellItem(newDocShellItem, aParent, sizeSpec);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче