зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1285898 - [e10s-multi] Localstorage "storage" event is not fired with multiple content processes. r=asuth
--HG-- extra : rebase_source : 724b38c52139dee1c6f746152fefff05333dfc24 extra : intermediate-source : e56108122b9088555f29a28e6086d4d117a68c4e extra : source : 6681b50c1f6d0d2d22d5f631234402e020c0b78a
This commit is contained in:
Родитель
09858c1716
Коммит
d32aa97041
|
@ -2179,7 +2179,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindow)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDoc)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleService)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWakeLock)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingStorageEvents)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleRequestExecutor)
|
||||
for (IdleRequest* request : tmp->mIdleRequestCallbacks) {
|
||||
|
@ -2260,7 +2259,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
|
|||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDoc)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleService)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWakeLock)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingStorageEvents)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleObservers)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mGamepads)
|
||||
|
@ -11904,49 +11902,66 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
bool isPrivateBrowsing = IsPrivateBrowsing();
|
||||
if ((!nsCRT::strcmp(aTopic, "dom-storage2-changed") && !isPrivateBrowsing) ||
|
||||
(!nsCRT::strcmp(aTopic, "dom-private-storage2-changed") && isPrivateBrowsing)) {
|
||||
if (!IsInnerWindow() || !AsInner()->IsCurrentInnerWindow()) {
|
||||
// We need these for our private-browsing check below; so save them off.
|
||||
// (And we can't do the private-browsing enforcement check as part of our
|
||||
// outer conditional because otherwise we'll trigger an NS_WARNING if control
|
||||
// flow reaches the bottom of this method.)
|
||||
bool isNonPrivateLocalStorageChange =
|
||||
!nsCRT::strcmp(aTopic, "dom-storage2-changed");
|
||||
bool isPrivateLocalStorageChange =
|
||||
!nsCRT::strcmp(aTopic, "dom-private-storage2-changed");
|
||||
if (isNonPrivateLocalStorageChange || isPrivateLocalStorageChange) {
|
||||
// Enforce that the source storage area's private browsing state matches
|
||||
// this window's state. These flag checks and their maintenance independent
|
||||
// from the principal's OriginAttributes matter because chrome docshells
|
||||
// that are part of private browsing windows can be private browsing without
|
||||
// having their OriginAttributes set (because they have the system
|
||||
// principal).
|
||||
bool isPrivateBrowsing = IsPrivateBrowsing();
|
||||
if ((isNonPrivateLocalStorageChange && isPrivateBrowsing) ||
|
||||
(isPrivateLocalStorageChange && !isPrivateBrowsing)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIPrincipal *principal;
|
||||
nsresult rv;
|
||||
// We require that aData be either u"SessionStorage" or u"localStorage".
|
||||
// Assert under debug, but ignore the bogus event under non-debug.
|
||||
MOZ_ASSERT(aData);
|
||||
if (!aData) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
// LocalStorage can only exist on an inner window, and we don't want to
|
||||
// generate events on frozen or otherwise-navigated-away from windows.
|
||||
// (Actually, this code used to try and buffer events for frozen windows,
|
||||
// but it never worked, so we've removed it. See bug 1285898.)
|
||||
if (!IsInnerWindow() || !AsInner()->IsCurrentInnerWindow() || IsFrozen()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIPrincipal *principal = GetPrincipal();
|
||||
if (!principal) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<StorageEvent> event = static_cast<StorageEvent*>(aSubject);
|
||||
if (!event) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
RefPtr<Storage> changingStorage = event->GetStorageArea();
|
||||
if (!changingStorage) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMStorage> istorage = changingStorage.get();
|
||||
|
||||
bool fireMozStorageChanged = false;
|
||||
nsAutoString eventType;
|
||||
eventType.AssignLiteral("storage");
|
||||
principal = GetPrincipal();
|
||||
if (!principal) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (changingStorage->IsPrivate() != IsPrivateBrowsing()) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (!NS_strcmp(aData, u"sessionStorage")) {
|
||||
nsCOMPtr<nsIDOMStorage> changingStorage = event->GetStorageArea();
|
||||
MOZ_ASSERT(changingStorage);
|
||||
|
||||
switch (changingStorage->GetType())
|
||||
{
|
||||
case Storage::SessionStorage:
|
||||
{
|
||||
bool check = false;
|
||||
|
||||
nsCOMPtr<nsIDOMStorageManager> storageManager = do_QueryInterface(GetDocShell());
|
||||
if (storageManager) {
|
||||
rv = storageManager->CheckStorage(principal, istorage, &check);
|
||||
nsresult rv = storageManager->CheckStorage(principal, changingStorage,
|
||||
&check);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -11967,58 +11982,48 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
if (fireMozStorageChanged) {
|
||||
eventType.AssignLiteral("MozSessionStorageChanged");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Storage::LocalStorage:
|
||||
{
|
||||
// Allow event fire only for the same principal storages
|
||||
// XXX We have to use EqualsIgnoreDomain after bug 495337 lands
|
||||
nsIPrincipal* storagePrincipal = changingStorage->GetPrincipal();
|
||||
else {
|
||||
MOZ_ASSERT(!NS_strcmp(aData, u"localStorage"));
|
||||
nsIPrincipal* storagePrincipal = event->GetPrincipal();
|
||||
if (!storagePrincipal) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool equals = false;
|
||||
rv = storagePrincipal->Equals(principal, &equals);
|
||||
nsresult rv = storagePrincipal->Equals(principal, &equals);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!equals)
|
||||
if (!equals) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
fireMozStorageChanged = mLocalStorage == event->GetStorageArea();
|
||||
|
||||
fireMozStorageChanged = mLocalStorage == changingStorage;
|
||||
if (fireMozStorageChanged) {
|
||||
eventType.AssignLiteral("MozLocalStorageChanged");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Clone the storage event included in the observer notification. We want
|
||||
// to dispatch clones rather than the original event.
|
||||
ErrorResult error;
|
||||
RefPtr<StorageEvent> newEvent = CloneStorageEvent(eventType, event, error);
|
||||
RefPtr<StorageEvent> clonedEvent =
|
||||
CloneStorageEvent(eventType, event, error);
|
||||
if (error.Failed()) {
|
||||
return error.StealNSResult();
|
||||
}
|
||||
|
||||
newEvent->SetTrusted(true);
|
||||
clonedEvent->SetTrusted(true);
|
||||
|
||||
if (fireMozStorageChanged) {
|
||||
WidgetEvent* internalEvent = newEvent->WidgetEventPtr();
|
||||
WidgetEvent* internalEvent = clonedEvent->WidgetEventPtr();
|
||||
internalEvent->mFlags.mOnlyChromeDispatch = true;
|
||||
}
|
||||
|
||||
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(newEvent);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool defaultActionEnabled;
|
||||
DispatchEvent(newEvent, &defaultActionEnabled);
|
||||
DispatchEvent(clonedEvent, &defaultActionEnabled);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -12109,10 +12114,19 @@ nsGlobalWindow::CloneStorageEvent(const nsAString& aType,
|
|||
aEvent->GetUrl(dict.mUrl);
|
||||
|
||||
RefPtr<Storage> storageArea = aEvent->GetStorageArea();
|
||||
MOZ_ASSERT(storageArea);
|
||||
|
||||
RefPtr<Storage> storage;
|
||||
if (storageArea->GetType() == Storage::LocalStorage) {
|
||||
|
||||
// If null, this is a localStorage event received by IPC.
|
||||
if (!storageArea) {
|
||||
storage = GetLocalStorage(aRv);
|
||||
if (aRv.Failed() || !storage) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// We must apply the current change to the 'local' localStorage.
|
||||
storage->ApplyEvent(aEvent);
|
||||
} else if (storageArea->GetType() == Storage::LocalStorage) {
|
||||
storage = GetLocalStorage(aRv);
|
||||
} else {
|
||||
MOZ_ASSERT(storageArea->GetType() == Storage::SessionStorage);
|
||||
|
@ -12124,7 +12138,7 @@ nsGlobalWindow::CloneStorageEvent(const nsAString& aType,
|
|||
}
|
||||
|
||||
MOZ_ASSERT(storage);
|
||||
MOZ_ASSERT(storage->IsForkOf(storageArea));
|
||||
MOZ_ASSERT_IF(storageArea, storage->IsForkOf(storageArea));
|
||||
|
||||
dict.mStorageArea = storage;
|
||||
|
||||
|
@ -12417,11 +12431,6 @@ nsGlobalWindow::FireDelayedDOMEvents()
|
|||
{
|
||||
FORWARD_TO_INNER(FireDelayedDOMEvents, (), NS_ERROR_UNEXPECTED);
|
||||
|
||||
for (uint32_t i = 0, len = mPendingStorageEvents.Length(); i < len; ++i) {
|
||||
Observe(mPendingStorageEvents[i], "dom-storage2-changed", nullptr);
|
||||
Observe(mPendingStorageEvents[i], "dom-private-storage2-changed", nullptr);
|
||||
}
|
||||
|
||||
if (mApplicationCache) {
|
||||
static_cast<nsDOMOfflineResourceList*>(mApplicationCache.get())->FirePendingEvents();
|
||||
}
|
||||
|
@ -13291,6 +13300,13 @@ nsGlobalWindow::EventListenerAdded(nsIAtom* aType)
|
|||
aType == nsGkAtoms::onvrdisplaypresentchange) {
|
||||
NotifyVREventListenerAdded();
|
||||
}
|
||||
|
||||
// We need to initialize localStorage in order to receive notifications.
|
||||
if (aType == nsGkAtoms::onstorage) {
|
||||
ErrorResult rv;
|
||||
GetLocalStorage(rv);
|
||||
rv.SuppressException();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -1943,9 +1943,6 @@ protected:
|
|||
// These member variables are used on both inner and the outer windows.
|
||||
nsCOMPtr<nsIPrincipal> mDocumentPrincipal;
|
||||
|
||||
typedef nsTArray<RefPtr<mozilla::dom::StorageEvent>> nsStorageEventArray;
|
||||
nsStorageEventArray mPendingStorageEvents;
|
||||
|
||||
uint32_t mSuspendDepth;
|
||||
uint32_t mFreezeDepth;
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#include "mozilla/dom/Event.h"
|
||||
#include "mozilla/dom/StorageEventBinding.h"
|
||||
|
||||
class nsIPrincipal;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
|
@ -34,6 +36,7 @@ protected:
|
|||
nsString mNewValue;
|
||||
nsString mUrl;
|
||||
RefPtr<Storage> mStorageArea;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
|
||||
public:
|
||||
virtual StorageEvent* AsStorageEvent();
|
||||
|
@ -79,6 +82,18 @@ public:
|
|||
{
|
||||
return mStorageArea;
|
||||
}
|
||||
|
||||
// Non WebIDL methods
|
||||
void SetPrincipal(nsIPrincipal* aPrincipal)
|
||||
{
|
||||
MOZ_ASSERT(!mPrincipal);
|
||||
mPrincipal = aPrincipal;
|
||||
}
|
||||
|
||||
nsIPrincipal* GetPrincipal() const
|
||||
{
|
||||
return mPrincipal;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "mozilla/dom/MemoryReportRequest.h"
|
||||
#include "mozilla/dom/ProcessGlobal.h"
|
||||
#include "mozilla/dom/PushNotifier.h"
|
||||
#include "mozilla/dom/Storage.h"
|
||||
#include "mozilla/dom/StorageIPC.h"
|
||||
#include "mozilla/dom/TabGroup.h"
|
||||
#include "mozilla/dom/workers/ServiceWorkerManager.h"
|
||||
|
@ -3035,6 +3036,20 @@ ContentChild::RecvBlobURLUnregistration(const nsCString& aURI)
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentChild::RecvDispatchLocalStorageChange(const nsString& aDocumentURI,
|
||||
const nsString& aKey,
|
||||
const nsString& aOldValue,
|
||||
const nsString& aNewValue,
|
||||
const IPC::Principal& aPrincipal,
|
||||
const bool& aIsPrivate)
|
||||
{
|
||||
Storage::DispatchStorageEvent(Storage::LocalStorage,
|
||||
aDocumentURI, aKey, aOldValue, aNewValue,
|
||||
aPrincipal, aIsPrivate, nullptr);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
#if defined(XP_WIN) && defined(ACCESSIBILITY)
|
||||
bool
|
||||
ContentChild::SendGetA11yContentId()
|
||||
|
|
|
@ -391,6 +391,14 @@ public:
|
|||
virtual mozilla::ipc::IPCResult
|
||||
RecvInitBlobURLs(nsTArray<BlobURLRegistrationData>&& aRegistations) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
RecvDispatchLocalStorageChange(const nsString& aDocumentURI,
|
||||
const nsString& aKey,
|
||||
const nsString& aOldValue,
|
||||
const nsString& aNewValue,
|
||||
const IPC::Principal& aPrincipal,
|
||||
const bool& aIsPrivate) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvLastPrivateDocShellDestroyed() override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvFilePathUpdate(const nsString& aStorageType,
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include "mozilla/dom/PContentPermissionRequestParent.h"
|
||||
#include "mozilla/dom/PCycleCollectWithLogsParent.h"
|
||||
#include "mozilla/dom/ServiceWorkerRegistrar.h"
|
||||
#include "mozilla/dom/Storage.h"
|
||||
#include "mozilla/dom/StorageIPC.h"
|
||||
#include "mozilla/dom/devicestorage/DeviceStorageRequestParent.h"
|
||||
#include "mozilla/dom/power/PowerManagerService.h"
|
||||
|
@ -4768,6 +4769,25 @@ ContentParent::RecvUnstoreAndBroadcastBlobURLUnregistration(const nsCString& aUR
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentParent::RecvBroadcastLocalStorageChange(const nsString& aDocumentURI,
|
||||
const nsString& aKey,
|
||||
const nsString& aOldValue,
|
||||
const nsString& aNewValue,
|
||||
const Principal& aPrincipal,
|
||||
const bool& aIsPrivate)
|
||||
{
|
||||
for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) {
|
||||
if (cp != this) {
|
||||
Unused << cp->SendDispatchLocalStorageChange(
|
||||
nsString(aDocumentURI), nsString(aKey), nsString(aOldValue),
|
||||
nsString(aNewValue), IPC::Principal(aPrincipal), aIsPrivate);
|
||||
}
|
||||
}
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentParent::RecvGetA11yContentId(uint32_t* aContentId)
|
||||
{
|
||||
|
|
|
@ -574,6 +574,14 @@ public:
|
|||
virtual mozilla::ipc::IPCResult
|
||||
RecvUnstoreAndBroadcastBlobURLUnregistration(const nsCString& aURI) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
RecvBroadcastLocalStorageChange(const nsString& aDocumentURI,
|
||||
const nsString& aKey,
|
||||
const nsString& aOldValue,
|
||||
const nsString& aNewValue,
|
||||
const IPC::Principal& aPrincipal,
|
||||
const bool& aIsPrivate) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
RecvGetA11yContentId(uint32_t* aContentId) override;
|
||||
|
||||
|
|
|
@ -676,6 +676,12 @@ child:
|
|||
|
||||
async BlobURLUnregistration(nsCString aURI);
|
||||
|
||||
async DispatchLocalStorageChange(nsString documentURI,
|
||||
nsString key,
|
||||
nsString oldValue,
|
||||
nsString newValue,
|
||||
Principal principal,
|
||||
bool isPrivate);
|
||||
|
||||
async GMPsChanged(GMPCapabilityData[] capabilities);
|
||||
|
||||
|
@ -1176,6 +1182,13 @@ parent:
|
|||
|
||||
async UnstoreAndBroadcastBlobURLUnregistration(nsCString url);
|
||||
|
||||
async BroadcastLocalStorageChange(nsString documentURI,
|
||||
nsString key,
|
||||
nsString oldValue,
|
||||
nsString newValue,
|
||||
Principal principal,
|
||||
bool isPrivate);
|
||||
|
||||
/**
|
||||
* Messages for communicating child Telemetry to the parent process
|
||||
*/
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
#include "nsIPrincipal.h"
|
||||
#include "nsICookiePermission.h"
|
||||
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/PermissionMessageUtils.h"
|
||||
#include "mozilla/dom/StorageBinding.h"
|
||||
#include "mozilla/dom/StorageEvent.h"
|
||||
#include "mozilla/dom/StorageEventBinding.h"
|
||||
|
@ -25,6 +28,9 @@
|
|||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace ipc;
|
||||
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Storage, mManager, mPrincipal, mWindow)
|
||||
|
@ -58,7 +64,6 @@ Storage::Storage(nsPIDOMWindowInner* aWindow,
|
|||
|
||||
Storage::~Storage()
|
||||
{
|
||||
mCache->KeepAlive();
|
||||
}
|
||||
|
||||
/* virtual */ JSObject*
|
||||
|
@ -215,6 +220,29 @@ void
|
|||
Storage::BroadcastChangeNotification(const nsSubstring& aKey,
|
||||
const nsSubstring& aOldValue,
|
||||
const nsSubstring& aNewValue)
|
||||
{
|
||||
if (!XRE_IsParentProcess() && GetType() == LocalStorage && mPrincipal) {
|
||||
// If we are in a child process, we want to send a message to the parent in
|
||||
// order to broadcast the StorageEvent correctly to any child process.
|
||||
dom::ContentChild* cc = dom::ContentChild::GetSingleton();
|
||||
Unused << NS_WARN_IF(!cc->SendBroadcastLocalStorageChange(
|
||||
mDocumentURI, nsString(aKey), nsString(aOldValue), nsString(aNewValue),
|
||||
IPC::Principal(mPrincipal), mIsPrivate));
|
||||
}
|
||||
|
||||
DispatchStorageEvent(GetType(), mDocumentURI, aKey, aOldValue, aNewValue,
|
||||
mPrincipal, mIsPrivate, this);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
Storage::DispatchStorageEvent(StorageType aStorageType,
|
||||
const nsAString& aDocumentURI,
|
||||
const nsAString& aKey,
|
||||
const nsAString& aOldValue,
|
||||
const nsAString& aNewValue,
|
||||
nsIPrincipal* aPrincipal,
|
||||
bool aIsPrivate,
|
||||
Storage* aStorage)
|
||||
{
|
||||
StorageEventInit dict;
|
||||
dict.mBubbles = false;
|
||||
|
@ -222,21 +250,62 @@ Storage::BroadcastChangeNotification(const nsSubstring& aKey,
|
|||
dict.mKey = aKey;
|
||||
dict.mNewValue = aNewValue;
|
||||
dict.mOldValue = aOldValue;
|
||||
dict.mStorageArea = this;
|
||||
dict.mUrl = mDocumentURI;
|
||||
dict.mStorageArea = aStorage;
|
||||
dict.mUrl = aDocumentURI;
|
||||
|
||||
// Note, this DOM event should never reach JS. It is cloned later in
|
||||
// nsGlobalWindow.
|
||||
RefPtr<StorageEvent> event =
|
||||
StorageEvent::Constructor(nullptr, NS_LITERAL_STRING("storage"), dict);
|
||||
|
||||
event->SetPrincipal(aPrincipal);
|
||||
|
||||
RefPtr<StorageNotifierRunnable> r =
|
||||
new StorageNotifierRunnable(event,
|
||||
GetType() == LocalStorage
|
||||
aStorageType == LocalStorage
|
||||
? u"localStorage"
|
||||
: u"sessionStorage",
|
||||
IsPrivate());
|
||||
aIsPrivate);
|
||||
NS_DispatchToMainThread(r);
|
||||
|
||||
// If we are in the parent process and we have the principal, we want to
|
||||
// broadcast this event to every other process.
|
||||
if (aStorageType == LocalStorage && XRE_IsParentProcess() && aPrincipal) {
|
||||
for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) {
|
||||
Unused << cp->SendDispatchLocalStorageChange(
|
||||
nsString(aDocumentURI), nsString(aKey), nsString(aOldValue),
|
||||
nsString(aNewValue), IPC::Principal(aPrincipal), aIsPrivate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Storage::ApplyEvent(StorageEvent* aStorageEvent)
|
||||
{
|
||||
MOZ_ASSERT(aStorageEvent);
|
||||
|
||||
nsAutoString key;
|
||||
nsAutoString old;
|
||||
nsAutoString value;
|
||||
|
||||
aStorageEvent->GetKey(key);
|
||||
aStorageEvent->GetNewValue(value);
|
||||
|
||||
// No key means clearing the full storage.
|
||||
if (key.IsVoid()) {
|
||||
MOZ_ASSERT(value.IsVoid());
|
||||
mCache->Clear(this);
|
||||
return;
|
||||
}
|
||||
|
||||
// No new value means removing the key.
|
||||
if (value.IsVoid()) {
|
||||
mCache->RemoveItem(this, key, old);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, we set the new value.
|
||||
mCache->SetItem(this, key, value, old);
|
||||
}
|
||||
|
||||
static const char kPermissionType[] = "cookie";
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace dom {
|
|||
|
||||
class StorageManagerBase;
|
||||
class StorageCache;
|
||||
class StorageEvent;
|
||||
|
||||
class Storage final
|
||||
: public nsIDOMStorage
|
||||
|
@ -129,6 +130,20 @@ public:
|
|||
return mCache == aOther->mCache;
|
||||
}
|
||||
|
||||
// aStorage can be null if this method is called by ContentChild.
|
||||
static void
|
||||
DispatchStorageEvent(StorageType aStorageType,
|
||||
const nsAString& aDocumentURI,
|
||||
const nsAString& aKey,
|
||||
const nsAString& aOldValue,
|
||||
const nsAString& aNewValue,
|
||||
nsIPrincipal* aPrincipal,
|
||||
bool aIsPrivate,
|
||||
Storage* aStorage);
|
||||
|
||||
void
|
||||
ApplyEvent(StorageEvent* aStorageEvent);
|
||||
|
||||
protected:
|
||||
// The method checks whether the caller can use a storage.
|
||||
// CanUseStorage is called before any DOM initiated operation
|
||||
|
|
|
@ -246,73 +246,6 @@ StorageCache::Preload()
|
|||
|
||||
namespace {
|
||||
|
||||
// This class is passed to timer as a tick observer. It refers the cache
|
||||
// and keeps it alive for a time.
|
||||
class StorageCacheHolder : public nsITimerCallback, public nsINamed
|
||||
{
|
||||
virtual ~StorageCacheHolder() {}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD
|
||||
Notify(nsITimer* aTimer) override
|
||||
{
|
||||
mCache = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
GetName(nsACString& aName) override
|
||||
{
|
||||
aName.AssignASCII("StorageCacheHolder_timer");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
SetName(const char* aName) override
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
RefPtr<StorageCache> mCache;
|
||||
|
||||
public:
|
||||
explicit StorageCacheHolder(StorageCache* aCache) : mCache(aCache) {}
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(StorageCacheHolder, nsITimerCallback, nsINamed)
|
||||
|
||||
} // namespace
|
||||
|
||||
void
|
||||
StorageCache::KeepAlive()
|
||||
{
|
||||
// Missing reference back to the manager means the cache is not responsible
|
||||
// for its lifetime. Used for keeping sessionStorage live forever.
|
||||
if (!mManager) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!NS_IsMainThread()) {
|
||||
// Timer and the holder must be initialized on the main thread.
|
||||
NS_DispatchToMainThread(NewRunnableMethod(this, &StorageCache::KeepAlive));
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
if (!timer) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<StorageCacheHolder> holder = new StorageCacheHolder(this);
|
||||
timer->InitWithCallback(holder, DOM_STORAGE_CACHE_KEEP_ALIVE_TIME_MS,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
|
||||
mKeepAliveTimer.swap(timer);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// The AutoTimer provided by telemetry headers is only using static,
|
||||
// i.e. compile time known ID, but here we know the ID only at run time.
|
||||
// Hence a new class.
|
||||
|
@ -680,9 +613,6 @@ StorageCache::LoadItem(const nsAString& aKey, const nsString& aValue)
|
|||
void
|
||||
StorageCache::LoadDone(nsresult aRv)
|
||||
{
|
||||
// Keep the preloaded cache alive for a time
|
||||
KeepAlive();
|
||||
|
||||
MonitorAutoLock monitor(mMonitor);
|
||||
mLoadResult = aRv;
|
||||
mLoaded = true;
|
||||
|
|
|
@ -96,10 +96,6 @@ public:
|
|||
// Starts async preload of this cache if it persistent and not loaded.
|
||||
void Preload();
|
||||
|
||||
// Keeps the cache alive (i.e. present in the manager's hash table) for a
|
||||
// time.
|
||||
void KeepAlive();
|
||||
|
||||
// The set of methods that are invoked by DOM storage web API.
|
||||
// We are passing the Storage object just to let the cache
|
||||
// read properties like mPrivate, mPrincipal and mSessionOnly.
|
||||
|
@ -196,9 +192,6 @@ private:
|
|||
// Obtained from the manager during initialization (Init method).
|
||||
RefPtr<StorageUsage> mUsage;
|
||||
|
||||
// Timer that holds this cache alive for a while after it has been preloaded.
|
||||
nsCOMPtr<nsITimer> mKeepAliveTimer;
|
||||
|
||||
// Principal the cache has been initially created for, this is used only for
|
||||
// sessionStorage access checks since sessionStorage objects are strictly
|
||||
// scoped by a principal. localStorage objects on the other hand are scoped
|
||||
|
|
|
@ -24,7 +24,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=674770
|
|||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function() {
|
||||
SpecialPowers.pushPrefEnv({"set":[["middlemouse.paste", true], ["dom.ipc.processCount", 1]]}, startTests);
|
||||
SpecialPowers.pushPrefEnv({"set":[["middlemouse.paste", true]]}, startTests);
|
||||
});
|
||||
|
||||
function startTests() {
|
||||
|
|
Загрузка…
Ссылка в новой задаче