diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 27994263c06..b9358c331ce 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -2676,6 +2676,12 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument, if (!aState) { if (reUseInnerWindow) { + + // The storage objects contain the URL of the window. We have to recreate + // them when the innerWindow is reused. + newInnerWindow->mLocalStorage = nullptr; + newInnerWindow->mSessionStorage = nullptr; + if (newInnerWindow->mDoc != aDocument) { newInnerWindow->mDoc = aDocument; @@ -11428,11 +11434,15 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic, // Clone the storage event included in the observer notification. We want // to dispatch clones rather than the original event. + ErrorResult error; nsRefPtr newEvent = CloneStorageEvent(fireMozStorageChanged ? NS_LITERAL_STRING("MozStorageChanged") : NS_LITERAL_STRING("storage"), - event); + event, error); + if (error.Failed()) { + return error.ErrorCode(); + } newEvent->SetTrusted(true); @@ -11528,7 +11538,8 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic, already_AddRefed nsGlobalWindow::CloneStorageEvent(const nsAString& aType, - const nsRefPtr& aEvent) + const nsRefPtr& aEvent, + ErrorResult& aRv) { MOZ_ASSERT(IsInnerWindow()); @@ -11540,7 +11551,26 @@ nsGlobalWindow::CloneStorageEvent(const nsAString& aType, aEvent->GetOldValue(dict.mOldValue); aEvent->GetNewValue(dict.mNewValue); aEvent->GetUrl(dict.mUrl); - dict.mStorageArea = aEvent->GetStorageArea(); + + nsRefPtr storageArea = aEvent->GetStorageArea(); + MOZ_ASSERT(storageArea); + + nsRefPtr storage; + if (storageArea->GetType() == DOMStorage::LocalStorage) { + storage = GetLocalStorage(aRv); + } else { + MOZ_ASSERT(storageArea->GetType() == DOMStorage::SessionStorage); + storage = GetSessionStorage(aRv); + } + + if (aRv.Failed() || !storage) { + return nullptr; + } + + MOZ_ASSERT(storage); + MOZ_ASSERT(storage->IsForkOf(storageArea)); + + dict.mStorageArea = storage; nsRefPtr event = StorageEvent::Constructor(this, aType, dict); return event.forget(); diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index d187f63d75b..850564da70d 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -1386,7 +1386,8 @@ protected: // Inner windows only. already_AddRefed CloneStorageEvent(const nsAString& aType, - const nsRefPtr& aEvent); + const nsRefPtr& aEvent, + mozilla::ErrorResult& aRv); // Outer windows only. nsDOMWindowList* GetWindowList(); diff --git a/dom/base/test/mochitest.ini b/dom/base/test/mochitest.ini index 8b8ac1b030c..f7bef0e3e27 100644 --- a/dom/base/test/mochitest.ini +++ b/dom/base/test/mochitest.ini @@ -24,6 +24,7 @@ skip-if = buildapp == 'mulet' [test_bug989665.html] [test_bug999456.html] [test_bug1022229.html] +[test_bug1043106.html] [test_clearTimeoutIntervalNoArg.html] [test_consoleEmptyStack.html] [test_constructor-assignment.html] diff --git a/dom/base/test/test_bug1043106.html b/dom/base/test/test_bug1043106.html new file mode 100644 index 00000000000..d55893acb1d --- /dev/null +++ b/dom/base/test/test_bug1043106.html @@ -0,0 +1,43 @@ + + + + + + Test for Bug 1043106 + + + + + Mozilla Bug 1043106 + + + + diff --git a/dom/src/storage/DOMStorage.h b/dom/src/storage/DOMStorage.h index ae79969adde..b9ffcce23cd 100644 --- a/dom/src/storage/DOMStorage.h +++ b/dom/src/storage/DOMStorage.h @@ -126,6 +126,12 @@ public: bool IsPrivate() const { return mIsPrivate; } bool IsSessionOnly() const { return mIsSessionOnly; } + bool IsForkOf(const DOMStorage* aOther) const + { + MOZ_ASSERT(aOther); + return mCache == aOther->mCache; + } + private: ~DOMStorage();