Bug 501423 - StorageEvent implementation does not match the spec, r=jst

This commit is contained in:
Honza Bambas 2010-01-28 15:53:53 +01:00
Родитель 740d3d8e2f
Коммит 450d622843
37 изменённых файлов: 1679 добавлений и 135 удалений

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

@ -1397,7 +1397,7 @@ SessionStoreService.prototype = {
// sessionStorage object for the page earlier than the page really
// requires it. It was causing problems while accessing a storage when
// a page later changed its domain.
storage = aDocShell.getSessionStorageForPrincipal(principal, false);
storage = aDocShell.getSessionStorageForPrincipal(principal, "", false);
if (storage)
storageItemCount = storage.length;
}
@ -2254,7 +2254,7 @@ SessionStoreService.prototype = {
_deserializeSessionStorage: function sss_deserializeSessionStorage(aStorageData, aDocShell) {
for (let url in aStorageData) {
let uri = IOSvc.newURI(url, null, null);
let storage = aDocShell.getSessionStorageForURI(uri);
let storage = aDocShell.getSessionStorageForURI(uri, "");
for (let key in aStorageData[url]) {
try {
storage.setItem(key, aStorageData[url][key]);

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

@ -51,6 +51,7 @@
#include "nsIContent.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsIDOM3Document.h"
#include "nsIDOMNSDocument.h"
#include "nsIDOMElement.h"
#include "nsIDOMStorageObsolete.h"
@ -2144,6 +2145,7 @@ GetPrincipalDomain(nsIPrincipal* aPrincipal, nsACString& aDomain)
NS_IMETHODIMP
nsDocShell::GetSessionStorageForPrincipal(nsIPrincipal* aPrincipal,
const nsAString& aDocumentURI,
PRBool aCreate,
nsIDOMStorage** aStorage)
{
@ -2165,7 +2167,9 @@ nsDocShell::GetSessionStorageForPrincipal(nsIPrincipal* aPrincipal,
nsDocShell* topDocShell = static_cast<nsDocShell*>(topItem.get());
if (topDocShell != this)
return topDocShell->GetSessionStorageForPrincipal(aPrincipal, aCreate,
return topDocShell->GetSessionStorageForPrincipal(aPrincipal,
aDocumentURI,
aCreate,
aStorage);
nsCAutoString currentDomain;
@ -2185,7 +2189,7 @@ nsDocShell::GetSessionStorageForPrincipal(nsIPrincipal* aPrincipal,
nsCOMPtr<nsPIDOMStorage> pistorage = do_QueryInterface(newstorage);
if (!pistorage)
return NS_ERROR_FAILURE;
rv = pistorage->InitAsSessionStorage(aPrincipal);
rv = pistorage->InitAsSessionStorage(aPrincipal, aDocumentURI);
if (NS_FAILED(rv))
return rv;
@ -2193,19 +2197,57 @@ nsDocShell::GetSessionStorageForPrincipal(nsIPrincipal* aPrincipal,
return NS_ERROR_OUT_OF_MEMORY;
newstorage.swap(*aStorage);
return NS_OK;
#if defined(PR_LOGGING) && defined(DEBUG)
PR_LOG(gDocShellLog, PR_LOG_DEBUG,
("nsDocShell[%p]: created a new sessionStorage %p",
this, *aStorage));
#endif
}
else if (*aStorage) {
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;
}
}
#if defined(PR_LOGGING) && defined(DEBUG)
PR_LOG(gDocShellLog, PR_LOG_DEBUG,
("nsDocShell[%p]: returns existing sessionStorage %p",
this, *aStorage));
#endif
}
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;
}
if (aCreate) {
// We are asked to create a new storage object. This indicates
// that a new windows wants it. At this moment we "fork" the existing
// storage object (what it means is described in the paragraph bellow).
// We must create a single object per a single window to distinguish
// a window originating oparations on the storage object to succesfully
// prevent dispatch of a storage event to this same window that ivoked
// a change in its storage. We also do this to correctly fill
// documentURI property in the storage event.
//
// The difference between clone and fork is that clone creates
// a completelly new and independent storage, but fork only creates
// a new object wrapping the storage implementation and data and
// the forked storage then behaves completelly the same way as
// the storage it has been forked of, all such forked storage objects
// shares their state and data and change on one such object affects
// all others the same way.
nsCOMPtr<nsPIDOMStorage> piStorage = do_QueryInterface(*aStorage);
nsCOMPtr<nsIDOMStorage> fork = piStorage->Fork(aDocumentURI);
#if defined(PR_LOGGING) && defined(DEBUG)
PR_LOG(gDocShellLog, PR_LOG_DEBUG,
("nsDocShell[%p]: forked sessionStorage %p to %p",
this, *aStorage, fork.get()));
#endif
fork.swap(*aStorage);
}
return NS_OK;
@ -2213,13 +2255,15 @@ nsDocShell::GetSessionStorageForPrincipal(nsIPrincipal* aPrincipal,
NS_IMETHODIMP
nsDocShell::GetSessionStorageForURI(nsIURI* aURI,
const nsAString& aDocumentURI,
nsIDOMStorage** aStorage)
{
return GetSessionStorageForURI(aURI, PR_TRUE, aStorage);
return GetSessionStorageForURI(aURI, aDocumentURI, PR_TRUE, aStorage);
}
nsresult
nsDocShell::GetSessionStorageForURI(nsIURI* aURI,
const nsSubstring& aDocumentURI,
PRBool aCreate,
nsIDOMStorage** aStorage)
{
@ -2240,7 +2284,7 @@ nsDocShell::GetSessionStorageForURI(nsIURI* aURI,
if (NS_FAILED(rv))
return rv;
return GetSessionStorageForPrincipal(principal, aCreate, aStorage);
return GetSessionStorageForPrincipal(principal, aDocumentURI, aCreate, aStorage);
}
nsresult
@ -2272,6 +2316,11 @@ nsDocShell::AddSessionStorage(nsIPrincipal* aPrincipal,
if (mStorages.GetWeak(currentDomain))
return NS_ERROR_NOT_AVAILABLE;
#if defined(PR_LOGGING) && defined(DEBUG)
PR_LOG(gDocShellLog, PR_LOG_DEBUG,
("nsDocShell[%p]: was added a sessionStorage %p",
this, aStorage));
#endif
if (!mStorages.Put(currentDomain, aStorage))
return NS_ERROR_OUT_OF_MEMORY;
}

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

@ -605,6 +605,7 @@ protected:
void ReattachEditorToWindow(nsISHEntry *aSHEntry);
nsresult GetSessionStorageForURI(nsIURI* aURI,
const nsSubstring& aDocumentURI,
PRBool create,
nsIDOMStorage** aStorage);

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

@ -70,7 +70,7 @@ interface nsIDOMStorage;
interface nsIPrincipal;
interface nsIWebBrowserPrint;
[scriptable, uuid(1067ee1a-08e8-455d-9b12-19eeeee56b8e)]
[scriptable, uuid(c95eaff1-14e6-4db1-a806-46be97d5a9b6)]
interface nsIDocShell : nsISupports
{
/**
@ -430,17 +430,23 @@ interface nsIDocShell : nsISupports
* If it doesn't already exist, a new one will be created.
*
* @param uri the uri of the storage object to retrieve
* @param documentURI new storage will be created with reference to this
* document.documentURI that will appear in storage event
*/
nsIDOMStorage getSessionStorageForURI(in nsIURI uri);
nsIDOMStorage getSessionStorageForURI(in nsIURI uri,
in DOMString documentURI);
/*
* Retrieves the WebApps session storage object for the supplied principal.
*
* @param principal returns a storage for this principal
* @param documentURI new storage will be created with reference to this
* document.documentURI that will appear in storage event
* @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 DOMString documentURI,
in boolean create);
/*

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

@ -1202,6 +1202,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(StorageEvent, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(StorageEventObsolete, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(DOMParser, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
@ -3487,6 +3489,10 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageEvent)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(StorageEventObsolete, nsIDOMStorageEventObsolete)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageEventObsolete)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(DOMParser, nsIDOMParser)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMParser)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMParserJS)

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

@ -383,6 +383,7 @@ enum nsDOMClassInfoID {
eDOMClassInfo_StorageList_id,
eDOMClassInfo_StorageItem_id,
eDOMClassInfo_StorageEvent_id,
eDOMClassInfo_StorageEventObsolete_id,
// DOMParser, XMLSerializer
eDOMClassInfo_DOMParser_id,

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

@ -101,6 +101,7 @@
#include "nsIDOMHTMLElement.h"
#include "nsIDOMCrypto.h"
#include "nsIDOMDocument.h"
#include "nsIDOM3Document.h"
#include "nsIDOMNSDocument.h"
#include "nsIDOMDocumentView.h"
#include "nsIDOMElement.h"
@ -113,6 +114,7 @@
#include "nsIDOMPopupBlockedEvent.h"
#include "nsIDOMOfflineResourceList.h"
#include "nsIDOMGeoGeolocation.h"
#include "nsPIDOMStorage.h"
#include "nsDOMString.h"
#include "nsIEmbeddingSiteWindow2.h"
#include "nsThreadUtils.h"
@ -653,9 +655,9 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
mTimeoutPublicIdCounter(1),
mTimeoutFiringDepth(0),
mJSObject(nsnull),
mPendingStorageEvents(nsnull),
mTimeoutsSuspendDepth(0),
mFocusMethod(0)
mFocusMethod(0),
mPendingStorageEventsObsolete(nsnull)
#ifdef DEBUG
, mSetOpenerWindowCalled(PR_FALSE)
#endif
@ -687,6 +689,7 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
// Watch for dom-storage-changed so we can fire storage
// events. Use a strong reference.
os->AddObserver(mObserver, "dom-storage2-changed", PR_FALSE);
os->AddObserver(mObserver, "dom-storage-changed", PR_FALSE);
}
}
@ -773,6 +776,7 @@ nsGlobalWindow::~nsGlobalWindow()
do_GetService("@mozilla.org/observer-service;1");
if (os) {
os->RemoveObserver(mObserver, NS_IOSERVICE_OFFLINE_STATUS_TOPIC);
os->RemoveObserver(mObserver, "dom-storage2-changed");
os->RemoveObserver(mObserver, "dom-storage-changed");
}
@ -826,7 +830,7 @@ nsGlobalWindow::~nsGlobalWindow()
nsCycleCollector_DEBUG_wasFreed(static_cast<nsIScriptGlobalObject*>(this));
#endif
delete mPendingStorageEvents;
delete mPendingStorageEventsObsolete;
nsLayoutStatics::Release();
}
@ -1730,6 +1734,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
mDocument = do_QueryInterface(aDocument);
mDoc = aDocument;
mLocalStorage = nsnull;
mSessionStorage = nsnull;
#ifdef DEBUG
mLastOpenedURI = aDocument->GetDocumentURI();
@ -7082,8 +7087,6 @@ nsGlobalWindow::GetSessionStorage(nsIDOMStorage ** aSessionStorage)
{
FORWARD_TO_INNER(GetSessionStorage, (aSessionStorage), NS_ERROR_UNEXPECTED);
*aSessionStorage = nsnull;
nsIPrincipal *principal = GetPrincipal();
nsIDocShell* docShell = GetDocShell();
@ -7091,15 +7094,56 @@ nsGlobalWindow::GetSessionStorage(nsIDOMStorage ** aSessionStorage)
return NS_OK;
}
nsresult rv = docShell->GetSessionStorageForPrincipal(principal,
PR_TRUE,
aSessionStorage);
NS_ENSURE_SUCCESS(rv, rv);
if (!*aSessionStorage) {
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
if (mSessionStorage) {
#ifdef PR_LOGGING
if (PR_LOG_TEST(gDOMLeakPRLog, PR_LOG_DEBUG)) {
PR_LogPrint("nsGlobalWindow %p has %p sessionStorage", this, mSessionStorage.get());
}
#endif
nsCOMPtr<nsPIDOMStorage> piStorage = do_QueryInterface(mSessionStorage);
if (piStorage) {
PRBool canAccess = piStorage->CanAccess(principal);
NS_ASSERTION(canAccess,
"window %x owned sessionStorage "
"that could not be accessed!");
if (!canAccess) {
mSessionStorage = nsnull;
}
}
}
if (!mSessionStorage) {
*aSessionStorage = nsnull;
nsString documentURI;
nsCOMPtr<nsIDOM3Document> document3 = do_QueryInterface(mDoc);
if (document3)
document3->GetDocumentURI(documentURI);
nsresult rv = docShell->GetSessionStorageForPrincipal(principal,
documentURI,
PR_TRUE,
getter_AddRefs(mSessionStorage));
NS_ENSURE_SUCCESS(rv, rv);
#ifdef PR_LOGGING
if (PR_LOG_TEST(gDOMLeakPRLog, PR_LOG_DEBUG)) {
PR_LogPrint("nsGlobalWindow %p tried to get a new sessionStorage %p", this, mSessionStorage.get());
}
#endif
if (!mSessionStorage) {
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
}
#ifdef PR_LOGGING
if (PR_LOG_TEST(gDOMLeakPRLog, PR_LOG_DEBUG)) {
PR_LogPrint("nsGlobalWindow %p returns %p sessionStorage", this, mSessionStorage.get());
}
#endif
NS_ADDREF(*aSessionStorage = mSessionStorage);
return NS_OK;
}
@ -7147,7 +7191,14 @@ nsGlobalWindow::GetLocalStorage(nsIDOMStorage ** aLocalStorage)
do_GetService("@mozilla.org/dom/storagemanager;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = storageManager->GetLocalStorageForPrincipal(principal, getter_AddRefs(mLocalStorage));
nsString documentURI;
nsCOMPtr<nsIDOM3Document> document3 = do_QueryInterface(mDoc);
if (document3)
document3->GetDocumentURI(documentURI);
rv = storageManager->GetLocalStorageForPrincipal(principal,
documentURI,
getter_AddRefs(mLocalStorage));
NS_ENSURE_SUCCESS(rv, rv);
}
@ -7290,21 +7341,7 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
nsresult rv;
principal = GetPrincipal();
if (!aData) {
nsIDocShell* docShell = GetDocShell();
if (principal && docShell) {
nsCOMPtr<nsIDOMStorage> storage;
docShell->GetSessionStorageForPrincipal(principal,
PR_FALSE,
getter_AddRefs(storage));
if (!SameCOMIdentity(storage, aSubject)) {
// A sessionStorage object changed, but not our session storage
// object.
return NS_OK;
}
}
} else if (principal) {
if (principal) {
// A global storage object changed, check to see if it's one
// this window can access.
@ -7338,23 +7375,23 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
// store the domain in which the change happened and fire the
// events if we're ever thawed.
if (!mPendingStorageEvents) {
mPendingStorageEvents = new nsDataHashtable<nsStringHashKey, PRBool>;
NS_ENSURE_TRUE(mPendingStorageEvents, NS_ERROR_OUT_OF_MEMORY);
if (!mPendingStorageEventsObsolete) {
mPendingStorageEventsObsolete = new nsDataHashtable<nsStringHashKey, PRBool>;
NS_ENSURE_TRUE(mPendingStorageEventsObsolete, NS_ERROR_OUT_OF_MEMORY);
rv = mPendingStorageEvents->Init();
rv = mPendingStorageEventsObsolete->Init();
NS_ENSURE_SUCCESS(rv, rv);
}
mPendingStorageEvents->Put(domain, PR_TRUE);
mPendingStorageEventsObsolete->Put(domain, PR_TRUE);
return NS_OK;
}
nsRefPtr<nsDOMStorageEvent> event = new nsDOMStorageEvent(domain);
nsRefPtr<nsDOMStorageEventObsolete> event = new nsDOMStorageEventObsolete();
NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
rv = event->Init();
rv = event->InitStorageEvent(NS_LITERAL_STRING("storage"), PR_FALSE, PR_FALSE, domain);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMHTMLDocument> htmlDoc(do_QueryInterface(mDocument));
@ -7373,7 +7410,99 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
}
PRBool defaultActionEnabled;
target->DispatchEvent((nsIDOMStorageEvent *)event, &defaultActionEnabled);
target->DispatchEvent((nsIDOMStorageEventObsolete *)event, &defaultActionEnabled);
return NS_OK;
}
if (IsInnerWindow() && !nsCRT::strcmp(aTopic, "dom-storage2-changed")) {
nsIPrincipal *principal;
nsresult rv;
nsCOMPtr<nsIDOMStorageEvent> event = do_QueryInterface(aSubject, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMStorage> changingStorage;
rv = event->GetStorageArea(getter_AddRefs(changingStorage));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsPIDOMStorage> pistorage = do_QueryInterface(changingStorage);
nsPIDOMStorage::nsDOMStorageType storageType = pistorage->StorageType();
principal = GetPrincipal();
switch (storageType)
{
case nsPIDOMStorage::SessionStorage:
{
if (SameCOMIdentity(mSessionStorage, changingStorage)) {
// Do not fire any events for the same storage object, it's not shared
// among windows, see nsGlobalWindow::GetSessionStoarge()
return NS_OK;
}
nsCOMPtr<nsIDOMStorage> storage = mSessionStorage;
if (!storage) {
nsIDocShell* docShell = GetDocShell();
if (principal && docShell) {
// No need to pass documentURI here, it's only needed when we want
// to create a new storage, the third paramater would be PR_TRUE
docShell->GetSessionStorageForPrincipal(principal,
EmptyString(),
PR_FALSE,
getter_AddRefs(storage));
}
}
if (!pistorage->IsForkOf(storage)) {
// This storage event is coming from a different doc shell,
// i.e. it is a clone, ignore this event.
return NS_OK;
}
#ifdef PR_LOGGING
if (PR_LOG_TEST(gDOMLeakPRLog, PR_LOG_DEBUG)) {
PR_LogPrint("nsGlobalWindow %p with sessionStorage %p passing event from %p", this, mSessionStorage.get(), pistorage.get());
}
#endif
break;
}
case nsPIDOMStorage::LocalStorage:
{
if (SameCOMIdentity(mLocalStorage, changingStorage)) {
// Do not fire any events for the same storage object, it's not shared
// among windows, see nsGlobalWindow::GetLocalStoarge()
return NS_OK;
}
// Allow event fire only for the same principal storages
// XXX We have to use EqualsIgnoreDomain after bug 495337 lands
nsIPrincipal *storagePrincipal = pistorage->Principal();
PRBool equals;
rv = storagePrincipal->Equals(principal, &equals);
NS_ENSURE_SUCCESS(rv, rv);
if (!equals)
return NS_OK;
break;
}
default:
return NS_OK;
}
if (IsFrozen()) {
// This window is frozen, rather than firing the events here,
// store the domain in which the change happened and fire the
// events if we're ever thawed.
mPendingStorageEvents.AppendElement(event);
return NS_OK;
}
PRBool defaultActionEnabled;
DispatchEvent((nsIDOMStorageEvent *)event, &defaultActionEnabled);
return NS_OK;
}
@ -7403,12 +7532,16 @@ nsGlobalWindow::FireDelayedDOMEvents()
{
FORWARD_TO_INNER(FireDelayedDOMEvents, (), NS_ERROR_UNEXPECTED);
if (mPendingStorageEvents) {
// Fire pending storage events.
mPendingStorageEvents->EnumerateRead(FirePendingStorageEvents, this);
for (PRUint32 i = 0; i < mPendingStorageEvents.Length(); ++i) {
Observe(mPendingStorageEvents[i], "dom-storage2-changed", nsnull);
}
delete mPendingStorageEvents;
mPendingStorageEvents = nsnull;
if (mPendingStorageEventsObsolete) {
// Fire pending storage events.
mPendingStorageEventsObsolete->EnumerateRead(FirePendingStorageEvents, this);
delete mPendingStorageEventsObsolete;
mPendingStorageEventsObsolete = nsnull;
}
if (mApplicationCache) {

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

@ -96,6 +96,7 @@
#include "nsIDOMStorageObsolete.h"
#include "nsIDOMStorageList.h"
#include "nsIDOMStorageWindow.h"
#include "nsIDOMStorageEvent.h"
#include "nsIDOMOfflineResourceList.h"
#include "nsPIDOMEventTarget.h"
#include "nsIArray.h"
@ -738,6 +739,7 @@ protected:
nsCOMPtr<nsIDOMCrypto> mCrypto;
nsCOMPtr<nsIDOMStorage> mLocalStorage;
nsCOMPtr<nsIDOMStorage> mSessionStorage;
nsCOMPtr<nsISupports> mInnerWindowHolders[NS_STID_ARRAY_UBOUND];
nsCOMPtr<nsIPrincipal> mOpenerScriptPrincipal; // strong; used to determine
@ -750,7 +752,6 @@ protected:
nsTimeout* mTimeoutInsertionPoint;
PRUint32 mTimeoutPublicIdCounter;
PRUint32 mTimeoutFiringDepth;
nsCOMPtr<nsIDOMStorageObsolete> mSessionStorage;
// Holder of the dummy java plugin, used to expose window.java and
// window.packages.
@ -761,7 +762,9 @@ protected:
nsCOMPtr<nsIDocument> mDoc; // For fast access to principals
JSObject* mJSObject;
nsDataHashtable<nsStringHashKey, PRBool> *mPendingStorageEvents;
typedef nsTArray<nsCOMPtr<nsIDOMStorageEvent> > nsDOMStorageEventArray;
nsDOMStorageEventArray mPendingStorageEvents;
nsDataHashtable<nsStringHashKey, PRBool> *mPendingStorageEventsObsolete;
PRUint32 mTimeoutsSuspendDepth;

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

@ -59,6 +59,7 @@ SDK_XPIDLSRCS = \
nsIDOMStorage.idl \
nsIDOMStorageObsolete.idl\
nsIDOMStorageEvent.idl \
nsIDOMStorageEventObsolete.idl \
nsIDOMStorageItem.idl \
nsIDOMStorageList.idl \
nsIDOMStorageWindow.idl \

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

@ -40,26 +40,57 @@
/**
* Interface for a client side storage. See
* http://www.whatwg.org/specs/web-apps/current-work/#scs-client-side
* http://dev.w3.org/html5/webstorage/#the-storage-event
* for more information.
*
* Event sent to a window when a storage area changes.
*/
[scriptable, uuid(8c021c75-f6b6-493c-914e-0b6c57ccc88d)]
interface nsIDOMStorage;
[scriptable, uuid(AE0CB688-68B3-4fb3-9A11-2DA8E620E808)]
interface nsIDOMStorageEvent : nsIDOMEvent
{
/**
* Domain of the storage area which changed, or #session for
* session storage.
* Attribute represents the key being changed. The key attribute is null
* when change has been invoked by the storage clear() method.
*/
readonly attribute DOMString domain;
readonly attribute DOMString key;
/**
* Initialize a storage event.
* The original value of the key. The oldValue is null when the change
* has been invoked by storage clear() method or the key has been newly
* added and therefor doesn't have any previous value.
*/
readonly attribute DOMString oldValue;
/**
* The new value of the key. The newValue is null when the change
* has been invoked by storage clear() method or the key has been removed
* from the storage.
*/
readonly attribute DOMString newValue;
/**
* Represents the address of the document whose key changed.
*/
readonly attribute DOMString url;
/**
* Represents the Storage object that was affected.
*/
readonly attribute nsIDOMStorage storageArea;
/**
* Initialize the event in a manner analogous to the similarly-named method
* in the DOM Events interfaces.
*/
void initStorageEvent(in DOMString typeArg,
in boolean canBubbleArg,
in boolean cancelableArg,
in DOMString domainArg);
in DOMString keyArg,
in DOMString oldValueArg,
in DOMString newValueArg,
in DOMString urlArg,
in nsIDOMStorage storageAreaArg);
};

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

@ -0,0 +1,65 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** 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.org code.
*
* The Initial Developer of the Original Code is
* Neil Deakin <enndeakin@sympatico.ca>
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of 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 "domstubs.idl"
#include "nsIDOMEvent.idl"
/**
* Interface for a client side storage. See
* http://www.whatwg.org/specs/web-apps/current-work/#scs-client-side
* for more information.
*
* Event sent to a window when a storage area changes.
*/
[scriptable, uuid(c0178907-847d-41c0-8a62-31301bb946fa)]
interface nsIDOMStorageEventObsolete : nsIDOMEvent
{
/**
* Domain of the storage area which changed, or #session for
* session storage.
*/
readonly attribute DOMString domain;
/**
* Initialize a storage event.
*/
void initStorageEvent(in DOMString typeArg,
in boolean canBubbleArg,
in boolean cancelableArg,
in DOMString domainArg);
};

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

@ -40,7 +40,7 @@
interface nsIDOMStorage;
interface nsIPrincipal;
[scriptable, uuid(c8e54beb-48f3-4538-a0ce-d6229f4d8f45)]
[scriptable, uuid(fd91ec36-7da8-43bb-b8f2-4b57a862a467)]
interface nsIDOMStorageManager : nsISupports
{
/**
@ -64,5 +64,6 @@ interface nsIDOMStorageManager : nsISupports
* This method ensures there is always only a single instance
* for a single origin.
*/
nsIDOMStorage getLocalStorageForPrincipal(in nsIPrincipal aPrincipal);
nsIDOMStorage getLocalStorageForPrincipal(in nsIPrincipal aPrincipal,
in DOMString aDocumentURI);
};

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

@ -47,25 +47,41 @@ class nsIDOMStorageObsolete;
class nsIURI;
class nsIPrincipal;
// {BAFFCEB1-FD40-4ea9-8378-3509DD79204A}
#define NS_PIDOMSTORAGE_IID \
{ 0x5ffbee8d, 0x9a86, 0x4a57, \
{ 0x8c, 0x63, 0x76, 0x56, 0x18, 0x9c, 0xb2, 0xbc } }
{ 0xbaffceb1, 0xfd40, 0x4ea9, \
{ 0x83, 0x78, 0x35, 0x9, 0xdd, 0x79, 0x20, 0x4a } }
class nsPIDOMStorage : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_PIDOMSTORAGE_IID)
virtual nsresult InitAsSessionStorage(nsIPrincipal *aPrincipal) = 0;
virtual nsresult InitAsLocalStorage(nsIPrincipal *aPrincipal) = 0;
typedef enum {
Unknown = 0,
GlobalStorage = 1,
LocalStorage = 2,
SessionStorage = 3
} nsDOMStorageType;
virtual nsresult InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI) = 0;
virtual nsresult InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI) = 0;
virtual nsresult InitAsGlobalStorage(const nsACString &aDomainDemanded) = 0;
virtual already_AddRefed<nsIDOMStorage> Clone() = 0;
virtual already_AddRefed<nsIDOMStorage> Fork(const nsSubstring &aDocumentURI) = 0;
virtual PRBool IsForkOf(nsIDOMStorage* aThat) = 0;
virtual nsTArray<nsString> *GetKeys() = 0;
virtual nsIPrincipal* Principal() = 0;
virtual PRBool CanAccess(nsIPrincipal *aPrincipal) = 0;
virtual nsDOMStorageType StorageType() = 0;
virtual void BroadcastChangeNotification(const nsSubstring &aKey,
const nsSubstring &aOldValue,
const nsSubstring &aNewValue) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsPIDOMStorage, NS_PIDOMSTORAGE_IID)

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

@ -64,6 +64,7 @@
#include "nsIPrivateBrowsingService.h"
#include "nsDOMString.h"
#include "nsNetCID.h"
#include "nsIProxyObjectManager.h"
static const PRUint32 ASK_BEFORE_ACCEPT = 1;
static const PRUint32 ACCEPT_SESSION = 2;
@ -436,6 +437,7 @@ nsDOMStorageManager::ClearOfflineApps()
NS_IMETHODIMP
nsDOMStorageManager::GetLocalStorageForPrincipal(nsIPrincipal *aPrincipal,
const nsSubstring &aDocumentURI,
nsIDOMStorage **aResult)
{
NS_ENSURE_ARG_POINTER(aPrincipal);
@ -447,7 +449,7 @@ nsDOMStorageManager::GetLocalStorageForPrincipal(nsIPrincipal *aPrincipal,
if (!storage)
return NS_ERROR_OUT_OF_MEMORY;
rv = storage->InitAsLocalStorage(aPrincipal);
rv = storage->InitAsLocalStorage(aPrincipal, aDocumentURI);
if (NS_FAILED(rv))
return rv;
@ -548,8 +550,9 @@ NS_NewDOMStorage2(nsISupports* aOuter, REFNSIID aIID, void** aResult)
nsDOMStorage::nsDOMStorage()
: mUseDB(PR_FALSE)
, mSessionOnly(PR_TRUE)
, mLocalStorage(PR_FALSE)
, mItemsCached(PR_FALSE)
, mStorageType(nsPIDOMStorage::Unknown)
, mEventBroadcaster(nsnull)
{
mSecurityChecker = this;
mItems.Init(8);
@ -560,12 +563,13 @@ nsDOMStorage::nsDOMStorage()
nsDOMStorage::nsDOMStorage(nsDOMStorage& aThat)
: mUseDB(PR_FALSE) // Any clone is not using the database
, mSessionOnly(PR_TRUE)
, mLocalStorage(PR_FALSE) // Any clone is not a localStorage
, mItemsCached(PR_FALSE)
, mDomain(aThat.mDomain)
, mStorageType(aThat.mStorageType)
#ifdef MOZ_STORAGE
, mScopeDBKey(aThat.mScopeDBKey)
#endif
, mEventBroadcaster(nsnull)
{
mSecurityChecker = this;
mItems.Init(8);
@ -610,7 +614,7 @@ GetDomainURI(nsIPrincipal *aPrincipal, PRBool aIncludeDomain, nsIURI **_domain)
}
nsresult
nsDOMStorage::InitAsSessionStorage(nsIPrincipal *aPrincipal)
nsDOMStorage::InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI)
{
nsCOMPtr<nsIURI> domainURI;
nsresult rv = GetDomainURI(aPrincipal, PR_TRUE, getter_AddRefs(domainURI));
@ -623,16 +627,20 @@ nsDOMStorage::InitAsSessionStorage(nsIPrincipal *aPrincipal)
// won't get to InitAsSessionStorage.
domainURI->GetAsciiHost(mDomain);
mDocumentURI = aDocumentURI;
#ifdef MOZ_STORAGE
mUseDB = PR_FALSE;
mScopeDBKey.Truncate();
mQuotaDomainDBKey.Truncate();
#endif
mStorageType = SessionStorage;
return NS_OK;
}
nsresult
nsDOMStorage::InitAsLocalStorage(nsIPrincipal *aPrincipal)
nsDOMStorage::InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI)
{
nsCOMPtr<nsIURI> domainURI;
nsresult rv = GetDomainURI(aPrincipal, PR_FALSE, getter_AddRefs(domainURI));
@ -646,6 +654,8 @@ nsDOMStorage::InitAsLocalStorage(nsIPrincipal *aPrincipal)
// mPrincipal in bug 455070. It is not even used for localStorage.
domainURI->GetAsciiHost(mDomain);
mDocumentURI = aDocumentURI;
#ifdef MOZ_STORAGE
nsDOMStorageDBWrapper::CreateOriginScopeDBKey(domainURI, mScopeDBKey);
@ -661,7 +671,7 @@ nsDOMStorage::InitAsLocalStorage(nsIPrincipal *aPrincipal)
PR_TRUE, PR_TRUE, mQuotaETLDplus1DomainDBKey);
#endif
mLocalStorage = PR_TRUE;
mStorageType = LocalStorage;
return NS_OK;
}
@ -684,6 +694,9 @@ nsDOMStorage::InitAsGlobalStorage(const nsACString &aDomainDemanded)
nsDOMStorageDBWrapper::CreateQuotaDomainDBKey(aDomainDemanded,
PR_TRUE, PR_TRUE, mQuotaETLDplus1DomainDBKey);
#endif
mStorageType = GlobalStorage;
mEventBroadcaster = this;
return NS_OK;
}
@ -995,6 +1008,9 @@ nsDOMStorage::SetItem(const nsAString& aKey, const nsAString& aData)
if (aKey.IsEmpty())
return NS_OK;
nsString oldValue;
SetDOMStringToNull(oldValue);
nsresult rv;
nsRefPtr<nsDOMStorageItem> newitem = nsnull;
nsSessionStorageEntry *entry = mItems.GetEntry(aKey);
@ -1002,9 +1018,8 @@ nsDOMStorage::SetItem(const nsAString& aKey, const nsAString& aData)
if (entry->mItem->IsSecure() && !IsCallerSecure()) {
return NS_ERROR_DOM_SECURITY_ERR;
}
if (!UseDB()) {
entry->mItem->SetValueInternal(aData);
}
oldValue = entry->mItem->GetValueInternal();
entry->mItem->SetValueInternal(aData);
}
else {
newitem = new nsDOMStorageItem(this, aKey, aData, IsCallerSecure());
@ -1023,9 +1038,8 @@ nsDOMStorage::SetItem(const nsAString& aKey, const nsAString& aData)
entry->mItem = newitem;
}
// SetDBValue already calls BroadcastChangeNotification so don't do it again
if (!UseDB())
BroadcastChangeNotification();
if ((oldValue != aData || mStorageType == GlobalStorage) && mEventBroadcaster)
mEventBroadcaster->BroadcastChangeNotification(aKey, oldValue, aData);
return NS_OK;
}
@ -1038,6 +1052,7 @@ NS_IMETHODIMP nsDOMStorage::RemoveItem(const nsAString& aKey)
if (aKey.IsEmpty())
return NS_OK;
nsString oldValue;
nsSessionStorageEntry *entry = mItems.GetEntry(aKey);
if (entry && entry->mItem->IsSecure() && !IsCallerSecure()) {
@ -1056,26 +1071,31 @@ NS_IMETHODIMP nsDOMStorage::RemoveItem(const nsAString& aKey)
return NS_OK;
NS_ENSURE_SUCCESS(rv, rv);
oldValue = value;
rv = gStorageDB->RemoveKey(this, aKey, !IsOfflineAllowed(mDomain),
aKey.Length() + value.Length());
NS_ENSURE_SUCCESS(rv, rv);
mItemsCached = PR_FALSE;
BroadcastChangeNotification();
#endif
}
else if (entry) {
// clear string as StorageItems may be referencing this item
oldValue = entry->mItem->GetValueInternal();
entry->mItem->ClearValue();
BroadcastChangeNotification();
}
if (entry) {
mItems.RawRemoveEntry(entry);
}
if ((!oldValue.IsEmpty() && mStorageType != GlobalStorage) && mEventBroadcaster) {
nsAutoString nullString;
SetDOMStringToNull(nullString);
mEventBroadcaster->BroadcastChangeNotification(aKey, oldValue, nullString);
}
return NS_OK;
}
@ -1100,6 +1120,8 @@ nsDOMStorage::Clear()
if (UseDB())
CacheKeysFromDB();
PRInt32 oldCount = mItems.Count();
PRBool foundSecureItem = PR_FALSE;
mItems.EnumerateEntries(CheckSecure, &foundSecureItem);
@ -1118,7 +1140,12 @@ nsDOMStorage::Clear()
#endif
mItems.Clear();
BroadcastChangeNotification();
if (oldCount && mEventBroadcaster) {
nsAutoString nullString;
SetDOMStringToNull(nullString);
mEventBroadcaster->BroadcastChangeNotification(nullString, nullString, nullString);
}
return NS_OK;
}
@ -1188,7 +1215,7 @@ nsDOMStorage::GetDBValue(const nsAString& aKey, nsAString& aValue,
nsAutoString value;
rv = gStorageDB->GetKeyValue(this, aKey, value, aSecure);
if (rv == NS_ERROR_DOM_NOT_FOUND_ERR && mLocalStorage) {
if (rv == NS_ERROR_DOM_NOT_FOUND_ERR && mStorageType != GlobalStorage) {
SetDOMStringToNull(aValue);
}
@ -1250,7 +1277,6 @@ nsDOMStorage::SetDBValue(const nsAString& aKey,
NS_ConvertUTF8toUTF16(mDomain).get());
}
BroadcastChangeNotification();
#endif
return NS_OK;
@ -1301,6 +1327,19 @@ nsDOMStorage::Clone()
return nsnull;
}
already_AddRefed<nsIDOMStorage>
nsDOMStorage::Fork(const nsSubstring &aDocumentURI)
{
NS_ASSERTION(PR_FALSE, "Old DOMStorage doesn't implement forking");
return nsnull;
}
PRBool nsDOMStorage::IsForkOf(nsIDOMStorage* aThat)
{
NS_ASSERTION(PR_FALSE, "Old DOMStorage doesn't implement forking");
return PR_FALSE;
}
struct KeysArrayBuilderStruct
{
PRBool callerIsSecure;
@ -1371,8 +1410,16 @@ nsDOMStorage::CanAccess(nsIPrincipal *aPrincipal)
return domain.Equals(mDomain);
}
nsPIDOMStorage::nsDOMStorageType
nsDOMStorage::StorageType()
{
return mStorageType;
}
void
nsDOMStorage::BroadcastChangeNotification()
nsDOMStorage::BroadcastChangeNotification(const nsSubstring &aKey,
const nsSubstring &aOldValue,
const nsSubstring &aNewValue)
{
nsresult rv;
nsCOMPtr<nsIObserverService> observerService =
@ -1386,7 +1433,7 @@ nsDOMStorage::BroadcastChangeNotification()
// domain, but if it's a global storage object we do.
observerService->NotifyObservers((nsIDOMStorageObsolete *)this,
"dom-storage-changed",
UseDB() ? NS_ConvertUTF8toUTF16(mDomain).get() : nsnull);
NS_ConvertUTF8toUTF16(mDomain).get());
}
//
@ -1422,7 +1469,7 @@ nsDOMStorage2::nsDOMStorage2(nsDOMStorage2& aThat)
}
nsresult
nsDOMStorage2::InitAsSessionStorage(nsIPrincipal *aPrincipal)
nsDOMStorage2::InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI)
{
mStorage = new nsDOMStorage();
if (!mStorage)
@ -1431,11 +1478,13 @@ nsDOMStorage2::InitAsSessionStorage(nsIPrincipal *aPrincipal)
// Leave security checks only for domain (nsDOMStorage implementation)
mStorage->mSecurityChecker = mStorage;
mPrincipal = aPrincipal;
return mStorage->InitAsSessionStorage(aPrincipal);
mDocumentURI = aDocumentURI;
return mStorage->InitAsSessionStorage(aPrincipal, aDocumentURI);
}
nsresult
nsDOMStorage2::InitAsLocalStorage(nsIPrincipal *aPrincipal)
nsDOMStorage2::InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI)
{
mStorage = new nsDOMStorage();
if (!mStorage)
@ -1443,7 +1492,9 @@ nsDOMStorage2::InitAsLocalStorage(nsIPrincipal *aPrincipal)
mStorage->mSecurityChecker = this;
mPrincipal = aPrincipal;
return mStorage->InitAsLocalStorage(aPrincipal);
mDocumentURI = aDocumentURI;
return mStorage->InitAsLocalStorage(aPrincipal, aDocumentURI);
}
nsresult
@ -1466,6 +1517,41 @@ nsDOMStorage2::Clone()
return storage;
}
already_AddRefed<nsIDOMStorage>
nsDOMStorage2::Fork(const nsSubstring &aDocumentURI)
{
nsRefPtr<nsDOMStorage2> storage = new nsDOMStorage2();
if (!storage)
return nsnull;
nsresult rv = storage->InitAsSessionStorageFork(mPrincipal, aDocumentURI, mStorage);
if (NS_FAILED(rv))
return nsnull;
nsIDOMStorage* result = static_cast<nsIDOMStorage*>(storage.get());
storage.forget();
return result;
}
PRBool nsDOMStorage2::IsForkOf(nsIDOMStorage* aThat)
{
if (!aThat)
return PR_FALSE;
nsDOMStorage2* storage = static_cast<nsDOMStorage2*>(aThat);
return mStorage == storage->mStorage;
}
nsresult
nsDOMStorage2::InitAsSessionStorageFork(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI, nsIDOMStorageObsolete* aStorage)
{
mPrincipal = aPrincipal;
mDocumentURI = aDocumentURI;
mStorage = static_cast<nsDOMStorage*>(aStorage);
return NS_OK;
}
nsTArray<nsString> *
nsDOMStorage2::GetKeys()
{
@ -1497,6 +1583,56 @@ nsDOMStorage2::CanAccess(nsIPrincipal *aPrincipal)
return subsumes;
}
nsPIDOMStorage::nsDOMStorageType
nsDOMStorage2::StorageType()
{
if (mStorage)
return mStorage->StorageType();
return nsPIDOMStorage::Unknown;
}
void
nsDOMStorage2::BroadcastChangeNotification(const nsSubstring &aKey,
const nsSubstring &aOldValue,
const nsSubstring &aNewValue)
{
nsresult rv;
nsCOMPtr<nsIDOMStorageEvent> event = new nsDOMStorageEvent();
rv = event->InitStorageEvent(NS_LITERAL_STRING("storage"),
PR_FALSE,
PR_FALSE,
aKey,
aOldValue,
aNewValue,
mDocumentURI,
static_cast<nsIDOMStorage*>(this));
if (NS_FAILED(rv)) {
return;
}
nsCOMPtr<nsIObserverService> observerService =
do_GetService("@mozilla.org/observer-service;1", &rv);
if (NS_FAILED(rv)) {
return;
}
nsCOMPtr<nsIObserverService> observerServiceProxy;
rv = NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
NS_GET_IID(nsIObserverService),
observerService,
NS_PROXY_ASYNC | NS_PROXY_ALWAYS,
getter_AddRefs(observerServiceProxy));
if (NS_FAILED(rv)) {
return;
}
// Fire off a notification that a storage object changed.
observerServiceProxy->NotifyObservers(event,
"dom-storage2-changed",
nsnull);
}
NS_IMETHODIMP
nsDOMStorage2::GetLength(PRUint32 *aLength)
{
@ -1518,18 +1654,21 @@ nsDOMStorage2::GetItem(const nsAString& aKey, nsAString &aData)
NS_IMETHODIMP
nsDOMStorage2::SetItem(const nsAString& aKey, const nsAString& aData)
{
mStorage->mEventBroadcaster = this;
return mStorage->SetItem(aKey, aData);
}
NS_IMETHODIMP
nsDOMStorage2::RemoveItem(const nsAString& aKey)
{
mStorage->mEventBroadcaster = this;
return mStorage->RemoveItem(aKey);
}
NS_IMETHODIMP
nsDOMStorage2::Clear()
{
mStorage->mEventBroadcaster = this;
return mStorage->Clear();
}
@ -1842,8 +1981,81 @@ NS_IMPL_ADDREF_INHERITED(nsDOMStorageEvent, nsDOMEvent)
NS_IMPL_RELEASE_INHERITED(nsDOMStorageEvent, nsDOMEvent)
/* readonly attribute DOMString key; */
NS_IMETHODIMP nsDOMStorageEvent::GetKey(nsAString & aKey)
{
aKey = mKey;
return NS_OK;
}
/* readonly attribute DOMString oldValue; */
NS_IMETHODIMP nsDOMStorageEvent::GetOldValue(nsAString & aOldValue)
{
aOldValue = mOldValue;
return NS_OK;
}
/* readonly attribute DOMString newValue; */
NS_IMETHODIMP nsDOMStorageEvent::GetNewValue(nsAString & aNewValue)
{
aNewValue = mNewValue;
return NS_OK;
}
/* readonly attribute DOMString url; */
NS_IMETHODIMP nsDOMStorageEvent::GetUrl(nsAString & aUrl)
{
aUrl = mUrl;
return NS_OK;
}
/* readonly attribute nsIDOMStorage storageArea; */
NS_IMETHODIMP nsDOMStorageEvent::GetStorageArea(nsIDOMStorage * *aStorageArea)
{
NS_ENSURE_ARG_POINTER(aStorageArea);
NS_ADDREF(*aStorageArea = mStorageArea);
return NS_OK;
}
/* void initStorageEvent (in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in DOMString keyArg, in DOMString oldValueArg, in DOMString newValueArg, in DOMString urlArg, in nsIDOMStorage storageAreaArg); */
NS_IMETHODIMP nsDOMStorageEvent::InitStorageEvent(const nsAString & typeArg,
PRBool canBubbleArg,
PRBool cancelableArg,
const nsAString & keyArg,
const nsAString & oldValueArg,
const nsAString & newValueArg,
const nsAString & urlArg,
nsIDOMStorage *storageAreaArg)
{
nsresult rv;
rv = InitEvent(typeArg, canBubbleArg, cancelableArg);
NS_ENSURE_SUCCESS(rv, rv);
mKey = keyArg;
mOldValue = oldValueArg;
mNewValue = newValueArg;
mUrl = urlArg;
mStorageArea = storageAreaArg;
return NS_OK;
}
// Obsolete globalStorage event
// QueryInterface implementation for nsDOMStorageEventObsolete
NS_INTERFACE_MAP_BEGIN(nsDOMStorageEventObsolete)
NS_INTERFACE_MAP_ENTRY(nsIDOMStorageEventObsolete)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(StorageEventObsolete)
NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
NS_IMPL_ADDREF_INHERITED(nsDOMStorageEventObsolete, nsDOMEvent)
NS_IMPL_RELEASE_INHERITED(nsDOMStorageEventObsolete, nsDOMEvent)
NS_IMETHODIMP
nsDOMStorageEvent::GetDomain(nsAString& aDomain)
nsDOMStorageEventObsolete::GetDomain(nsAString& aDomain)
{
// mDomain will be #session for session storage for events that fire
// due to a change in a session storage object.
@ -1852,21 +2064,8 @@ nsDOMStorageEvent::GetDomain(nsAString& aDomain)
return NS_OK;
}
nsresult
nsDOMStorageEvent::Init()
{
nsresult rv = InitEvent(NS_LITERAL_STRING("storage"), PR_TRUE, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
// This init method is only called by native code, so set the
// trusted flag here.
SetTrusted(PR_TRUE);
return NS_OK;
}
NS_IMETHODIMP
nsDOMStorageEvent::InitStorageEvent(const nsAString& aTypeArg,
nsDOMStorageEventObsolete::InitStorageEvent(const nsAString& aTypeArg,
PRBool aCanBubbleArg,
PRBool aCancelableArg,
const nsAString& aDomainArg)

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

@ -55,6 +55,7 @@
#include "nsIDOMToString.h"
#include "nsDOMEvent.h"
#include "nsIDOMStorageEvent.h"
#include "nsIDOMStorageEventObsolete.h"
#include "nsIDOMStorageManager.h"
#include "nsCycleCollectionParticipant.h"
@ -145,13 +146,19 @@ public:
nsresult Clear();
// nsPIDOMStorage
virtual nsresult InitAsSessionStorage(nsIPrincipal *aPrincipal);
virtual nsresult InitAsLocalStorage(nsIPrincipal *aPrincipal);
virtual nsresult InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI);
virtual nsresult InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI);
virtual nsresult InitAsGlobalStorage(const nsACString &aDomainDemanded);
virtual already_AddRefed<nsIDOMStorage> Clone();
virtual already_AddRefed<nsIDOMStorage> Fork(const nsSubstring &aDocumentURI);
virtual PRBool IsForkOf(nsIDOMStorage* aThat);
virtual nsTArray<nsString> *GetKeys();
virtual nsIPrincipal* Principal();
virtual PRBool CanAccess(nsIPrincipal *aPrincipal);
virtual nsDOMStorageType StorageType();
virtual void BroadcastChangeNotification(const nsSubstring &aKey,
const nsSubstring &aOldValue,
const nsSubstring &aNewValue);
// If true, the contents of the storage should be stored in the
// database, otherwise this storage should act like a session
@ -218,13 +225,17 @@ protected:
// cache the keys from the database for faster lookup
nsresult CacheKeysFromDB();
void BroadcastChangeNotification();
PRBool CanAccessSystem(nsIPrincipal *aPrincipal);
// true if the storage database should be used for values
PRPackedBool mUseDB;
// domain this store is associated with
nsCString mDomain;
// document URI of the document this storage is bound to
nsString mDocumentURI;
// true if the preferences indicates that this storage should be
// session only. This member is updated by
// CacheStoragePermissions(), using the current principal.
@ -236,14 +247,11 @@ protected:
// objects are scoped to scheme/host/port in the database, while globalStorage
// objects are scoped just to host. this flag also tells the manager to map
// this storage also in mLocalStorages hash table.
PRPackedBool mLocalStorage;
nsDOMStorageType mStorageType;
// true if items from the database are cached
PRPackedBool mItemsCached;
// domain this store is associated with
nsCString mDomain;
// the key->value item pairs
nsTHashtable<nsSessionStorageEntry> mItems;
@ -255,6 +263,7 @@ protected:
friend class nsIDOMStorage2;
nsPIDOMStorage* mSecurityChecker;
nsPIDOMStorage* mEventBroadcaster;
public:
// e.g. "moc.rab.oof.:" or "moc.rab.oof.:http:80" depending
@ -288,19 +297,32 @@ public:
NS_DECL_NSIDOMSTORAGE
// nsPIDOMStorage
virtual nsresult InitAsSessionStorage(nsIPrincipal *aPrincipal);
virtual nsresult InitAsLocalStorage(nsIPrincipal *aPrincipal);
virtual nsresult InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI);
virtual nsresult InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI);
virtual nsresult InitAsGlobalStorage(const nsACString &aDomainDemanded);
virtual already_AddRefed<nsIDOMStorage> Clone();
virtual already_AddRefed<nsIDOMStorage> Fork(const nsSubstring &aDocumentURI);
virtual PRBool IsForkOf(nsIDOMStorage* aThat);
virtual nsTArray<nsString> *GetKeys();
virtual nsIPrincipal* Principal();
virtual PRBool CanAccess(nsIPrincipal *aPrincipal);
virtual nsDOMStorageType StorageType();
virtual void BroadcastChangeNotification(const nsSubstring &aKey,
const nsSubstring &aOldValue,
const nsSubstring &aNewValue);
nsresult InitAsSessionStorageFork(nsIPrincipal *aPrincipal,
const nsSubstring &aDocumentURI,
nsIDOMStorageObsolete* aStorage);
private:
// storages bound to an origin hold the principal to
// make security checks against it
nsCOMPtr<nsIPrincipal> mPrincipal;
// Needed for the storage event, this is address of the document this storage
// is bound to
nsString mDocumentURI;
nsRefPtr<nsDOMStorage> mStorage;
};
@ -422,15 +444,9 @@ class nsDOMStorageEvent : public nsDOMEvent,
public nsIDOMStorageEvent
{
public:
nsDOMStorageEvent(const nsAString& aDomain)
: nsDOMEvent(nsnull, nsnull), mDomain(aDomain)
nsDOMStorageEvent()
: nsDOMEvent(nsnull, nsnull)
{
if (aDomain.IsEmpty()) {
// An empty domain means this event is for a session sotrage
// object change. Store #session as the domain.
mDomain = NS_LITERAL_STRING("#session");
}
}
virtual ~nsDOMStorageEvent()
@ -443,6 +459,31 @@ public:
NS_DECL_NSIDOMSTORAGEEVENT
NS_FORWARD_NSIDOMEVENT(nsDOMEvent::)
protected:
nsString mKey;
nsString mOldValue;
nsString mNewValue;
nsString mUrl;
nsCOMPtr<nsIDOMStorage> mStorageArea;
};
class nsDOMStorageEventObsolete : public nsDOMEvent,
public nsIDOMStorageEventObsolete
{
public:
nsDOMStorageEventObsolete()
: nsDOMEvent(nsnull, nsnull)
{
}
virtual ~nsDOMStorageEventObsolete()
{
}
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMSTORAGEEVENTOBSOLETE
NS_FORWARD_NSIDOMEVENT(nsDOMEvent::)
protected:
nsString mDomain;
};

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

@ -55,6 +55,7 @@ DIRS += \
geolocation \
localstorage \
sessionstorage \
storageevent \
$(NULL)
include $(topsrcdir)/config/rules.mk

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

@ -20,7 +20,7 @@ function startTest()
var uri = ios.newURI(url, "", null);
var principal = ssm.getCodebasePrincipal(uri);
var storage = dsm.getLocalStorageForPrincipal(principal);
var storage = dsm.getLocalStorageForPrincipal(principal, "");
storage.setItem("chromekey", "chromevalue");

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

@ -0,0 +1,71 @@
#
# ***** 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.org code.
#
# The Initial Developer of the Original Code is
# Mozilla Corporation.
# Portions created by the Initial Developer are Copyright (C) 2008
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Jan Bambas <honzab@firemni.cz>
#
# Alternatively, the contents of this file may be used under the terms of
# either of 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 *****
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = dom/tests/mochitest/storageevent
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_TEST_FILES = \
frameGlobalStorageMaster.html \
frameGlobalStorageSlaveEqual.html \
frameGlobalStorageSlaveNotEqual.html \
frameLocalStorageMaster.html \
frameLocalStorageSlaveEqual.html \
frameLocalStorageSlaveNotEqual.html \
frameSessionStorageMasterEqual.html \
frameSessionStorageMasterNotEqual.html \
frameSessionStorageSlaveEqual.html \
frameSessionStorageSlaveNotEqual.html \
test_storageGlobalStorageEventCheckNoPropagation.html \
test_storageGlobalStorageEventCheckPropagation.html \
test_storageLocalStorageEventCheckNoPropagation.html \
test_storageLocalStorageEventCheckPropagation.html \
test_storageSessionStorageEventCheckPropagation.html \
test_storageSessionStorageEventCheckNoPropagation.html \
interOriginFrame.js \
interOriginTest2.js \
$(NULL)
libs:: $(_TEST_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)

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

@ -0,0 +1,53 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>master frame for event storage propagation</title>
<script type="text/javascript" src="interOriginFrame.js"></script>
<script type="text/javascript">
var currentStep = 1;
var gotEvent = false;
function bind()
{
document.body.addEventListener("storage", function(event)
{
gotEvent = true;
}, false);
}
function doStep()
{
switch (currentStep)
{
case 1:
var storage = globalStorage[location.host];
storage.setItem("X", "1");
storage.setItem("X", "2");
storage.setItem("X", "2");
storage.removeItem("X");
storage.removeItem("X");
storage.removeItem("Y");
storage.setItem("X", "2");
break;
case 3:
todo(gotEvent, false, "Expected no events");
return finishTest();
}
// Increase by two to distinguish each test step order
// in both master doStep and slave doStep functions.
++currentStep;
++currentStep;
return true;
}
</script>
</head>
<body onload="bind(); postMsg('frame loaded');">
</body>
</html>

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

@ -0,0 +1,56 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>slave for storage event propagation</title>
<script type="text/javascript" src="interOriginFrame.js"></script>
<script type="text/javascript">
var currentStep = 2;
var events = [];
function bind()
{
document.body.addEventListener("storage", function(event)
{
events.push(event);
}, false);
}
function doStep()
{
function checkEvent()
{
var event = events.shift();
ok(event);
if (!event)
return;
is(event.domain, "example.com");
}
switch (currentStep)
{
case 2:
is(events.length, 4, "Expected 5 events");
checkEvent();
checkEvent();
checkEvent();
checkEvent();
break;
}
// Increase by two to distinguish each test step order
// in both master doStep and slave doStep functions.
++currentStep;
++currentStep;
return true;
}
</script>
</head>
<body onload="bind(); postMsg('frame loaded');">
</body>
</html>

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

@ -0,0 +1,42 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>slave for storage event propagation</title>
<script type="text/javascript" src="interOriginFrame.js"></script>
<script type="text/javascript">
var currentStep = 2;
var gotEvent = false;
function bind()
{
document.body.addEventListener("storage", function(event)
{
gotEvent = true;
}, false);
}
function doStep()
{
switch (currentStep)
{
case 2:
is(gotEvent, false, "Expected no events");
break;
}
// Increase by two to distinguish each test step order
// in both master doStep and slave doStep functions.
++currentStep;
++currentStep;
return true;
}
</script>
</head>
<body onload="bind(); postMsg('frame loaded');">
</body>
</html>

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

@ -0,0 +1,63 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>master frame for event storage propagation</title>
<script type="text/javascript" src="interOriginFrame.js"></script>
<script type="text/javascript">
var currentStep = 1;
var gotEvent = false;
window.addEventListener("storage", function(event)
{
gotEvent = true;
}, false);
function doStep()
{
switch (currentStep)
{
case 1:
// Must not fire (storage must be clear!)
localStorage.clear();
// Must fire X:null->'1'
localStorage.setItem("X", "1");
// Must fire X:'1'->'2'
localStorage.setItem("X", "2");
// Must not fire
localStorage.setItem("X", "2");
// Must fire X:'2'->null
localStorage.removeItem("X");
// Must not fire
localStorage.removeItem("X");
// Must not fire
localStorage.removeItem("Y");
// Must fire X:null->'2' (we need something in the storage)
localStorage.setItem("X", "2");
// Must fire null:null->null (one item has been erased)
localStorage.clear();
// Must not fire
localStorage.clear();
break;
// Wait some time to let the async event be propagated
case 11:
is(gotEvent, false, "Expected no events");
return finishTest();
}
// Increase by two to distinguish each test step order
// in both master doStep and slave doStep functions.
++currentStep;
++currentStep;
return true;
}
</script>
</head>
<body onload="postMsg('frame loaded');">
</body>
</html>

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

@ -0,0 +1,55 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>slave for storage event propagation</title>
<script type="text/javascript" src="interOriginFrame.js"></script>
<script type="text/javascript">
var currentStep = 2;
var events = [];
window.addEventListener("storage", function(event)
{
events.push(event);
}, false);
function doStep()
{
function checkEvent(expectedKey, expectedOldValue, expectedNewValue)
{
var event = events.shift();
is(event.key, expectedKey, "key name check");
is(event.oldValue, expectedOldValue, "old value check");
is(event.newValue, expectedNewValue, "new value check");
is(event.url, "http://example.com/tests/dom/tests/mochitest/storageevent/frameLocalStorageMaster.html");
ok(event.storageArea);
}
switch (currentStep)
{
case 10:
is(events.length, 5, "Expected 5 events");
checkEvent("X", null, "1");
checkEvent("X", "1", "2");
checkEvent("X", "2", null);
checkEvent("X", null, "2");
checkEvent(null, null, null);
break;
}
// Increase by two to distinguish each test step order
// in both master doStep and slave doStep functions.
++currentStep;
++currentStep;
return true;
}
</script>
</head>
<body onload="postMsg('frame loaded');">
</body>
</html>

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

@ -0,0 +1,39 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>slave for storage event propagation</title>
<script type="text/javascript" src="interOriginFrame.js"></script>
<script type="text/javascript">
var currentStep = 2;
var gotEvent = false;
window.addEventListener("storage", function(event)
{
gotEvent = true;
}, false);
function doStep()
{
switch (currentStep)
{
case 10:
is(gotEvent, false, "Expected no events");
break;
}
// Increase by two to distinguish each test step order
// in both master doStep and slave doStep functions.
++currentStep;
++currentStep;
return true;
}
</script>
</head>
<body onload="postMsg('frame loaded');">
</body>
</html>

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

@ -0,0 +1,67 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>master frame for event storage propagation</title>
<script type="text/javascript" src="interOriginFrame.js"></script>
<script type="text/javascript">
var currentStep = 1;
var gotEvent = false;
window.addEventListener("storage", function(event)
{
gotEvent = true;
}, false);
function doStep()
{
switch (currentStep)
{
// In step 2 we instantiate sessionStorage in the other frame
case 1:
// Must not fire (storage must be clear!)
sessionStorage.clear();
// Must fire X:null->'1'
sessionStorage.setItem("X", "1");
// Must fire X:'1'->'2'
sessionStorage.setItem("X", "2");
// Must not fire
sessionStorage.setItem("X", "2");
// Must fire X:'2'->null
sessionStorage.removeItem("X");
// Must not fire
sessionStorage.removeItem("X");
// Must not fire
sessionStorage.removeItem("Y");
// Must fire X:null->'2' (we need something in the storage)
sessionStorage.setItem("X", "2");
// Must fire null:null->null (one item has been erased)
sessionStorage.clear();
// Must not fire
sessionStorage.clear();
break;
// Wait some time to let the async event be propagated
case 11:
is(gotEvent, false, "Expected no events");
return finishTest();
}
// Increase by two to distinguish each test step order
// in both master doStep and slave doStep functions.
++currentStep;
++currentStep;
return true;
}
</script>
</head>
<body onload="postMsg('frame loaded');">
<iframe src="http://example.com:80/tests/dom/tests/mochitest/storageevent/frameSessionStorageSlaveEqual.html"
name="slaveFrame">
</iframe>
</body>
</html>

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

@ -0,0 +1,66 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>master frame for event storage propagation</title>
<script type="text/javascript" src="interOriginFrame.js"></script>
<script type="text/javascript">
var currentStep = 1;
var gotEvent = false;
window.addEventListener("storage", function(event)
{
gotEvent = true;
}, false);
function doStep()
{
switch (currentStep)
{
case 1:
// Must not fire (storage must be clear!)
sessionStorage.clear();
// Must fire X:null->'1'
sessionStorage.setItem("X", "1");
// Must fire X:'1'->'2'
sessionStorage.setItem("X", "2");
// Must not fire
sessionStorage.setItem("X", "2");
// Must fire X:'2'->null
sessionStorage.removeItem("X");
// Must not fire
sessionStorage.removeItem("X");
// Must not fire
sessionStorage.removeItem("Y");
// Must fire X:null->'2' (we need something in the storage)
sessionStorage.setItem("X", "2");
// Must fire null:null->null (one item has been erased)
sessionStorage.clear();
// Must not fire
sessionStorage.clear();
break;
// Wait some time to let the async event be propagated
case 11:
is(gotEvent, false, "Expected no events");
return finishTest();
}
// Increase by two to distinguish each test step order
// in both master doStep and slave doStep functions.
++currentStep;
++currentStep;
return true;
}
</script>
</head>
<body onload="postMsg('frame loaded');">
<iframe src="http://example.com:80/tests/dom/tests/mochitest/storageevent/frameSessionStorageSlaveNotEqual.html"
name="slaveFrame">
</iframe>
</body>
</html>

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

@ -0,0 +1,59 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>slave for storage event propagation</title>
<script type="text/javascript" src="interOriginFrame.js"></script>
<script type="text/javascript">
var currentStep = 2;
var events = [];
window.addEventListener("storage", function(event)
{
events.push(event);
}, false);
function doStep()
{
function checkEvent(expectedKey, expectedOldValue, expectedNewValue)
{
var event = events.shift();
ok(event, "Event is present");
if (!event)
return;
is(event.key, expectedKey, "key name check");
is(event.oldValue, expectedOldValue, "old value check");
is(event.newValue, expectedNewValue, "new value check");
is(event.url, "http://example.com/tests/dom/tests/mochitest/storageevent/frameSessionStorageMasterEqual.html");
ok(event.storageArea);
}
switch (currentStep)
{
case 10:
is(events.length, 5, "Expected 5 events");
checkEvent("X", null, "1");
checkEvent("X", "1", "2");
checkEvent("X", "2", null);
checkEvent("X", null, "2");
checkEvent(null, null, null);
break;
}
// Increase by two to distinguish each test step order
// in both master doStep and slave doStep functions.
++currentStep;
++currentStep;
return true;
}
</script>
</head>
<body onload="postMsg('frame loaded');">
</body>
</html>

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

@ -0,0 +1,39 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>slave for storage event propagation</title>
<script type="text/javascript" src="interOriginFrame.js"></script>
<script type="text/javascript">
var currentStep = 2;
var gotEvent = false;
window.addEventListener("storage", function(event)
{
gotEvent = true;
}, false);
function doStep()
{
switch (currentStep)
{
case 10:
is(gotEvent, false, "Expected no events");
break;
}
// Increase by two to distinguish each test step order
// in both master doStep and slave doStep functions.
++currentStep;
++currentStep;
return true;
}
</script>
</head>
<body onload="postMsg('frame loaded');">
</body>
</html>

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

@ -0,0 +1,57 @@
function postMsg(message)
{
netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
var l = parent.window.location;
parent.postMessage(message, l.protocol + "//" + l.host);
}
window.addEventListener("message", onMessageReceived, false);
function onMessageReceived(event)
{
if (event.data == "step") {
var performed = false;
try {
performed = doStep();
}
catch (ex) {
postMsg("FAILURE: exception threw at "+ location +":\n" + ex);
finishTest();
}
if (performed)
postMsg("perf");
return;
}
if (parent)
postMsg(event.data);
}
function ok(a, message)
{
if (!a)
postMsg("FAILURE: " + message);
else
postMsg(message);
}
function is(a, b, message)
{
if (a != b)
postMsg("FAILURE: " + message + ", expected "+b+" got "+a);
else
postMsg(message + ", expected "+b+" got "+a);
}
function todo(a, b, message)
{
postMsg("TODO: " + message + ", expected "+b+" got "+a);
}
function finishTest()
{
postMsg("done");
return false;
}

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

@ -0,0 +1,58 @@
var frameLoadsPending = 2;
var callMasterFrame = true;
var testDone = false;
var masterFrameOrigin = "";
var slaveFrameOrigin = "";
var failureRegExp = new RegExp("^FAILURE");
var todoRegExp = new RegExp("^TODO");
const framePath = "/tests/dom/tests/mochitest/storageevent/";
window.addEventListener("message", onMessageReceived, false);
function onMessageReceived(event)
{
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
switch (event.data)
{
// Indication of the frame onload event
case "frame loaded":
if (--frameLoadsPending)
break;
// Just fall through...
// Indication of successfully finished step of a test
case "perf":
if (callMasterFrame)
masterFrame.postMessage("step", masterFrameOrigin);
else if (slaveFrame)
slaveFrame.postMessage("step", slaveFrameOrigin);
else if (masterFrame.slaveFrame)
masterFrame.slaveFrame.postMessage("step", slaveFrameOrigin);
callMasterFrame = !callMasterFrame;
break;
// Indication of all test parts finish (from any of the frames)
case "done":
if (testDone)
break;
testDone = true;
SimpleTest.finish();
break;
// Any other message indicates error, succes or todo message of a test
default:
if (event.data.match(todoRegExp))
SimpleTest.todo(false, event.data);
else
SimpleTest.ok(!event.data.match(failureRegExp), event.data);
break;
}
}

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

@ -0,0 +1,44 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>storage event propagation test</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="interOriginTest2.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<!--
This test loads two frames from different
origins and checks that entries of localStorage
objects don't leak each between other.
The subsystem is based on postMessage and addEventListener
to send messages among different origins. The subsystem waits
for both frames be loaded and then alternately calls each frames'
doStep() function that on each call proceeds with a single step
of the test on its side. This way the subsystem alternate between
both frames until both sequences completely finish.
-->
<script type="text/javascript">
function startTest()
{
masterFrameOrigin = "http://example.com:80";
slaveFrameOrigin = "http://example.org:80";
masterFrame.location = masterFrameOrigin + framePath + "frameGlobalStorageMaster.html";
slaveFrame.location = slaveFrameOrigin + framePath + "frameGlobalStorageSlaveNotEqual.html";
}
SimpleTest.waitForExplicitFinish();
</script>
</head>
<body onload="startTest();">
<iframe src="" name="masterFrame"></iframe>
<iframe src="" name="slaveFrame"></iframe>
</body>
</html>

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

@ -0,0 +1,44 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>storage event propagation test</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="interOriginTest2.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<!--
This test loads two frames from different
origins and checks that entries of localStorage
objects don't leak each between other.
The subsystem is based on postMessage and addEventListener
to send messages among different origins. The subsystem waits
for both frames be loaded and then alternately calls each frames'
doStep() function that on each call proceeds with a single step
of the test on its side. This way the subsystem alternate between
both frames until both sequences completely finish.
-->
<script type="text/javascript">
function startTest()
{
masterFrameOrigin = "http://example.com:80";
slaveFrameOrigin = "http://example.com:80";
masterFrame.location = masterFrameOrigin + framePath + "frameGlobalStorageMaster.html";
slaveFrame.location = slaveFrameOrigin + framePath + "frameGlobalStorageSlaveEqual.html";
}
SimpleTest.waitForExplicitFinish();
</script>
</head>
<body onload="startTest();">
<iframe src="" name="masterFrame"></iframe>
<iframe src="" name="slaveFrame"></iframe>
</body>
</html>

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

@ -0,0 +1,44 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>storage event propagation test</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="interOriginTest2.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<!--
This test loads two frames from different
origins and checks that entries of localStorage
objects don't leak each between other.
The subsystem is based on postMessage and addEventListener
to send messages among different origins. The subsystem waits
for both frames be loaded and then alternately calls each frames'
doStep() function that on each call proceeds with a single step
of the test on its side. This way the subsystem alternate between
both frames until both sequences completely finish.
-->
<script type="text/javascript">
function startTest()
{
masterFrameOrigin = "http://example.com:80";
slaveFrameOrigin = "http://example.org:80";
masterFrame.location = masterFrameOrigin + framePath + "frameLocalStorageMaster.html";
slaveFrame.location = slaveFrameOrigin + framePath + "frameLocalStorageSlaveNotEqual.html";
}
SimpleTest.waitForExplicitFinish();
</script>
</head>
<body onload="startTest();">
<iframe src="" name="masterFrame"></iframe>
<iframe src="" name="slaveFrame"></iframe>
</body>
</html>

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

@ -0,0 +1,44 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>storage event propagation test</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="interOriginTest2.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<!--
This test loads two frames from different
origins and checks that entries of localStorage
objects don't leak each between other.
The subsystem is based on postMessage and addEventListener
to send messages among different origins. The subsystem waits
for both frames be loaded and then alternately calls each frames'
doStep() function that on each call proceeds with a single step
of the test on its side. This way the subsystem alternate between
both frames until both sequences completely finish.
-->
<script type="text/javascript">
function startTest()
{
masterFrameOrigin = "http://example.com:80";
slaveFrameOrigin = "http://example.com:80";
masterFrame.location = masterFrameOrigin + framePath + "frameLocalStorageMaster.html";
slaveFrame.location = slaveFrameOrigin + framePath + "frameLocalStorageSlaveEqual.html";
}
SimpleTest.waitForExplicitFinish();
</script>
</head>
<body onload="startTest();">
<iframe src="" name="masterFrame"></iframe>
<iframe src="" name="slaveFrame"></iframe>
</body>
</html>

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

@ -0,0 +1,44 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>storage event propagation test</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="interOriginTest2.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<!--
This test loads two frames from different
origins and checks that entries of localStorage
objects don't leak each between other.
The subsystem is based on postMessage and addEventListener
to send messages among different origins. The subsystem waits
for both frames be loaded and then alternately calls each frames'
doStep() function that on each call proceeds with a single step
of the test on its side. This way the subsystem alternate between
both frames until both sequences completely finish.
-->
<script type="text/javascript">
var slaveFrame = null;
function startTest()
{
masterFrameOrigin = "http://example.org:80";
slaveFrameOrigin = "http://example.com:80";
masterFrame.location = masterFrameOrigin + framePath + "frameSessionStorageMasterNotEqual.html";
}
SimpleTest.waitForExplicitFinish();
</script>
</head>
<body onload="startTest();">
<iframe src="" name="masterFrame"></iframe>
</body>
</html>

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

@ -0,0 +1,44 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>storage event propagation test</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="interOriginTest2.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<!--
This test loads two frames from different
origins and checks that entries of localStorage
objects don't leak each between other.
The subsystem is based on postMessage and addEventListener
to send messages among different origins. The subsystem waits
for both frames be loaded and then alternately calls each frames'
doStep() function that on each call proceeds with a single step
of the test on its side. This way the subsystem alternate between
both frames until both sequences completely finish.
-->
<script type="text/javascript">
var slaveFrame = null;
function startTest()
{
masterFrameOrigin = "http://example.com:80";
slaveFrameOrigin = "http://example.com:80";
masterFrame.location = masterFrameOrigin + framePath + "frameSessionStorageMasterEqual.html";
}
SimpleTest.waitForExplicitFinish();
</script>
</head>
<body onload="startTest();">
<iframe src="" name="masterFrame"></iframe>
</body>
</html>

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

@ -950,7 +950,8 @@ nsWindowWatcher::OpenWindowJSInternal(nsIDOMWindow *aParent,
if (subjectPrincipal && parentDocShell) {
nsCOMPtr<nsIDOMStorage> storage;
parentDocShell->GetSessionStorageForPrincipal(subjectPrincipal, PR_FALSE,
parentDocShell->GetSessionStorageForPrincipal(subjectPrincipal,
EmptyString(), PR_FALSE,
getter_AddRefs(storage));
nsCOMPtr<nsPIDOMStorage> piStorage =
do_QueryInterface(storage);