mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 12:51:06 +00:00
Bug 1475599 - part 8 - CookieStore API - e10s support, r=smaug,cookie-reviewers,timhuang
Differential Revision: https://phabricator.services.mozilla.com/D217574
This commit is contained in:
parent
c993dc5823
commit
05ebc836d2
@ -7,6 +7,7 @@
|
||||
#include "CookieStore.h"
|
||||
#include "CookieStoreChild.h"
|
||||
#include "CookieStoreNotifier.h"
|
||||
#include "CookieStoreNotificationWatcherWrapper.h"
|
||||
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
@ -219,6 +220,10 @@ already_AddRefed<CookieStore> CookieStore::Create(nsIGlobalObject* aGlobal) {
|
||||
CookieStore::CookieStore(nsIGlobalObject* aGlobal)
|
||||
: DOMEventTargetHelper(aGlobal) {
|
||||
mNotifier = CookieStoreNotifier::Create(this);
|
||||
|
||||
// This must be created _after_ CookieStoreNotifier because we rely on the
|
||||
// notification order.
|
||||
mNotificationWatcher = CookieStoreNotificationWatcherWrapper::Create(this);
|
||||
}
|
||||
|
||||
CookieStore::~CookieStore() { Shutdown(); }
|
||||
@ -324,6 +329,21 @@ already_AddRefed<Promise> CookieStore::Set(const CookieInit& aOptions,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self->mNotificationWatcher) {
|
||||
promise->MaybeReject(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
nsID operationID;
|
||||
rv = nsID::GenerateUUIDInPlace(operationID);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
promise->MaybeReject(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
self->mNotificationWatcher->ResolvePromiseWhenNotified(operationID,
|
||||
promise);
|
||||
|
||||
RefPtr<CookieStoreChild::SetRequestPromise> ipcPromise =
|
||||
self->mActor->SendSetRequest(
|
||||
aOptions.mDomain.IsEmpty() ? nsString(baseDomain)
|
||||
@ -336,7 +356,7 @@ already_AddRefed<Promise> CookieStore::Set(const CookieInit& aOptions,
|
||||
? INT64_MAX
|
||||
: static_cast<int64_t>(aOptions.mExpires.Value() / 1000),
|
||||
path, SameSiteToConst(aOptions.mSameSite),
|
||||
aOptions.mPartitioned);
|
||||
aOptions.mPartitioned, operationID);
|
||||
if (NS_WARN_IF(!ipcPromise)) {
|
||||
promise->MaybeResolveWithUndefined();
|
||||
return;
|
||||
@ -344,9 +364,15 @@ already_AddRefed<Promise> CookieStore::Set(const CookieInit& aOptions,
|
||||
|
||||
ipcPromise->Then(
|
||||
NS_GetCurrentThread(), __func__,
|
||||
[promise = RefPtr<dom::Promise>(promise)](
|
||||
[promise = RefPtr<dom::Promise>(promise), self = RefPtr(self),
|
||||
operationID](
|
||||
const CookieStoreChild::SetRequestPromise::ResolveOrRejectValue&
|
||||
aResult) { promise->MaybeResolveWithUndefined(); });
|
||||
aResult) {
|
||||
if (!aResult.ResolveValue()) {
|
||||
self->mNotificationWatcher->ForgetOperationID(operationID);
|
||||
promise->MaybeResolveWithUndefined();
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
return promise.forget();
|
||||
@ -416,24 +442,44 @@ already_AddRefed<Promise> CookieStore::Delete(
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self->mNotificationWatcher) {
|
||||
promise->MaybeReject(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
nsID operationID;
|
||||
rv = nsID::GenerateUUIDInPlace(operationID);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
promise->MaybeReject(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
self->mNotificationWatcher->ResolvePromiseWhenNotified(operationID,
|
||||
promise);
|
||||
|
||||
RefPtr<CookieStoreChild::DeleteRequestPromise> ipcPromise =
|
||||
self->mActor->SendDeleteRequest(
|
||||
aOptions.mDomain.IsEmpty() ? nsString(baseDomain)
|
||||
: nsString(aOptions.mDomain),
|
||||
cookiePrincipal->OriginAttributesRef(),
|
||||
nsString(aOptions.mName), path, aOptions.mPartitioned);
|
||||
nsString(aOptions.mName), path, aOptions.mPartitioned,
|
||||
operationID);
|
||||
if (NS_WARN_IF(!ipcPromise)) {
|
||||
promise->MaybeResolveWithUndefined();
|
||||
return;
|
||||
}
|
||||
|
||||
ipcPromise->Then(NS_GetCurrentThread(), __func__,
|
||||
[promise = RefPtr<dom::Promise>(promise)](
|
||||
const CookieStoreChild::DeleteRequestPromise::
|
||||
ResolveOrRejectValue& aResult) {
|
||||
MOZ_ASSERT(aResult.IsResolve());
|
||||
promise->MaybeResolveWithUndefined();
|
||||
});
|
||||
ipcPromise->Then(
|
||||
NS_GetCurrentThread(), __func__,
|
||||
[promise = RefPtr<dom::Promise>(promise), self = RefPtr(self),
|
||||
operationID](const CookieStoreChild::DeleteRequestPromise::
|
||||
ResolveOrRejectValue& aResult) {
|
||||
MOZ_ASSERT(aResult.IsResolve());
|
||||
if (!aResult.ResolveValue()) {
|
||||
self->mNotificationWatcher->ForgetOperationID(operationID);
|
||||
promise->MaybeResolveWithUndefined();
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
return promise.forget();
|
||||
|
@ -17,6 +17,7 @@ namespace mozilla::dom {
|
||||
|
||||
class CookieData;
|
||||
class CookieStoreChild;
|
||||
class CookieStoreNotificationWatcherWrapper;
|
||||
class CookieStoreNotifier;
|
||||
class Promise;
|
||||
|
||||
@ -72,6 +73,7 @@ class CookieStore final : public DOMEventTargetHelper {
|
||||
|
||||
RefPtr<CookieStoreChild> mActor;
|
||||
RefPtr<CookieStoreNotifier> mNotifier;
|
||||
RefPtr<CookieStoreNotificationWatcherWrapper> mNotificationWatcher;
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
129
dom/cookiestore/CookieStoreNotificationWatcher.cpp
Normal file
129
dom/cookiestore/CookieStoreNotificationWatcher.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "CookieStoreNotificationWatcher.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "nsICookie.h"
|
||||
#include "nsICookieNotification.h"
|
||||
#include "nsIObserverService.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
NS_IMPL_ISUPPORTS(CookieStoreNotificationWatcher, nsIObserver,
|
||||
nsISupportsWeakReference)
|
||||
|
||||
// static
|
||||
already_AddRefed<CookieStoreNotificationWatcher>
|
||||
CookieStoreNotificationWatcher::Create(bool aPrivateBrowsing) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
RefPtr<CookieStoreNotificationWatcher> watcher =
|
||||
new CookieStoreNotificationWatcher();
|
||||
|
||||
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
|
||||
if (NS_WARN_IF(!os)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsresult rv = os->AddObserver(
|
||||
watcher, aPrivateBrowsing ? "private-cookie-changed" : "cookie-changed",
|
||||
true);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return watcher.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CookieStoreNotificationWatcher::Observe(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
const char16_t* aData) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsCOMPtr<nsICookieNotification> notification = do_QueryInterface(aSubject);
|
||||
NS_ENSURE_TRUE(notification, NS_ERROR_FAILURE);
|
||||
|
||||
nsID* operationID = nullptr;
|
||||
nsresult rv = notification->GetOperationID(&operationID);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!operationID) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < mPendingOperations.Length(); ++i) {
|
||||
PendingOperation& pendingOperation = mPendingOperations[i];
|
||||
if (pendingOperation.mOperationID.Equals(*operationID)) {
|
||||
pendingOperation.mCallback();
|
||||
mPendingOperations.RemoveElementAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void CookieStoreNotificationWatcher::CallbackWhenNotified(
|
||||
const nsID& aOperationID, MoveOnlyFunction<void()> aCallback) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
mPendingOperations.AppendElement(
|
||||
PendingOperation{std::move(aCallback), aOperationID});
|
||||
}
|
||||
|
||||
void CookieStoreNotificationWatcher::ForgetOperationID(
|
||||
const nsID& aOperationID) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
for (uint32_t i = 0; i < mPendingOperations.Length(); ++i) {
|
||||
PendingOperation& pendingOperation = mPendingOperations[i];
|
||||
if (pendingOperation.mOperationID.Equals(aOperationID)) {
|
||||
mPendingOperations.RemoveElementAt(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void CookieStoreNotificationWatcher::ReleaseOnMainThread(
|
||||
already_AddRefed<CookieStoreNotificationWatcher> aWatcher) {
|
||||
RefPtr<CookieStoreNotificationWatcher> watcher(aWatcher);
|
||||
|
||||
if (!watcher || NS_IsMainThread()) {
|
||||
return;
|
||||
}
|
||||
|
||||
class ReleaseWatcher final : public Runnable {
|
||||
public:
|
||||
explicit ReleaseWatcher(
|
||||
already_AddRefed<CookieStoreNotificationWatcher> aWatcher)
|
||||
: Runnable("ReleaseWatcher"), mDoomed(std::move(aWatcher)) {}
|
||||
|
||||
NS_IMETHOD Run() override {
|
||||
mDoomed = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
~ReleaseWatcher() {
|
||||
// If we still have to release the watcher, better to leak it.
|
||||
if (mDoomed) {
|
||||
Unused << mDoomed.forget().take();
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<CookieStoreNotificationWatcher> mDoomed;
|
||||
};
|
||||
|
||||
RefPtr<ReleaseWatcher> runnable(new ReleaseWatcher(watcher.forget()));
|
||||
NS_DispatchToMainThread(runnable);
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
51
dom/cookiestore/CookieStoreNotificationWatcher.h
Normal file
51
dom/cookiestore/CookieStoreNotificationWatcher.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_CookieStoreNotificationWatcher_h
|
||||
#define mozilla_dom_CookieStoreNotificationWatcher_h
|
||||
|
||||
#include "nsIObserver.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "mozilla/OriginAttributes.h"
|
||||
#include "mozilla/MoveOnlyFunction.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
class CookieStoreNotificationWatcher final : public nsIObserver,
|
||||
public nsSupportsWeakReference {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
static already_AddRefed<CookieStoreNotificationWatcher> Create(
|
||||
bool aPrivateBrowsing);
|
||||
|
||||
static void ReleaseOnMainThread(
|
||||
already_AddRefed<CookieStoreNotificationWatcher> aWatcher);
|
||||
|
||||
void CallbackWhenNotified(const nsID& aOperationID,
|
||||
MoveOnlyFunction<void()> aCallback);
|
||||
void ForgetOperationID(const nsID& aOperationID);
|
||||
|
||||
private:
|
||||
CookieStoreNotificationWatcher() = default;
|
||||
~CookieStoreNotificationWatcher() = default;
|
||||
|
||||
void MaybeResolveOperations(const nsID* aOperationID);
|
||||
|
||||
struct PendingOperation {
|
||||
MoveOnlyFunction<void()> mCallback;
|
||||
nsID mOperationID;
|
||||
};
|
||||
|
||||
// This is a simple list because I don't think we will have so many concurrent
|
||||
// operations to motivate an hash table.
|
||||
nsTArray<PendingOperation> mPendingOperations;
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
||||
#endif /* mozilla_dom_CookieStoreNotificationWatcher_h */
|
158
dom/cookiestore/CookieStoreNotificationWatcherWrapper.cpp
Normal file
158
dom/cookiestore/CookieStoreNotificationWatcherWrapper.cpp
Normal file
@ -0,0 +1,158 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "CookieStoreNotificationWatcherWrapper.h"
|
||||
#include "CookieStoreNotificationWatcher.h"
|
||||
#include "CookieStore.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/WorkerPrivate.h"
|
||||
#include "mozilla/dom/WorkerRef.h"
|
||||
#include "nsProxyRelease.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
// static
|
||||
already_AddRefed<CookieStoreNotificationWatcherWrapper>
|
||||
CookieStoreNotificationWatcherWrapper::Create(CookieStore* aCookieStore) {
|
||||
MOZ_ASSERT(aCookieStore);
|
||||
|
||||
nsIPrincipal* principal = nullptr;
|
||||
|
||||
if (!NS_IsMainThread()) {
|
||||
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
principal = workerPrivate->GetPrincipal();
|
||||
} else {
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = aCookieStore->GetOwnerWindow();
|
||||
MOZ_ASSERT(window);
|
||||
|
||||
nsCOMPtr<Document> document = window->GetExtantDoc();
|
||||
if (NS_WARN_IF(!document)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
principal = document->NodePrincipal();
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!principal)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<CookieStoreNotificationWatcherWrapper> wrapper =
|
||||
new CookieStoreNotificationWatcherWrapper();
|
||||
|
||||
bool privateBrowsing = principal->OriginAttributesRef().IsPrivateBrowsing();
|
||||
|
||||
if (!NS_IsMainThread()) {
|
||||
NS_DispatchToMainThread(
|
||||
NS_NewRunnableFunction(__func__, [wrapper, privateBrowsing] {
|
||||
wrapper->CreateWatcherOnMainThread(privateBrowsing);
|
||||
}));
|
||||
} else {
|
||||
wrapper->CreateWatcherOnMainThread(privateBrowsing);
|
||||
}
|
||||
|
||||
return wrapper.forget();
|
||||
}
|
||||
|
||||
CookieStoreNotificationWatcherWrapper::
|
||||
~CookieStoreNotificationWatcherWrapper() {
|
||||
CookieStoreNotificationWatcher::ReleaseOnMainThread(
|
||||
mWatcherOnMainThread.forget());
|
||||
}
|
||||
|
||||
void CookieStoreNotificationWatcherWrapper::CreateWatcherOnMainThread(
|
||||
bool aPrivateBrowsing) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mWatcherOnMainThread =
|
||||
CookieStoreNotificationWatcher::Create(aPrivateBrowsing);
|
||||
}
|
||||
|
||||
void CookieStoreNotificationWatcherWrapper::ForgetOperationID(
|
||||
const nsID& aOperationID) {
|
||||
if (!NS_IsMainThread()) {
|
||||
NS_DispatchToMainThread(
|
||||
NS_NewRunnableFunction(__func__, [self = RefPtr(this), aOperationID] {
|
||||
self->ForgetOperationID(aOperationID);
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
if (mWatcherOnMainThread) {
|
||||
mWatcherOnMainThread->ForgetOperationID(aOperationID);
|
||||
}
|
||||
}
|
||||
|
||||
void CookieStoreNotificationWatcherWrapper::ResolvePromiseWhenNotified(
|
||||
const nsID& aOperationID, Promise* aPromise) {
|
||||
MOZ_ASSERT(aPromise);
|
||||
|
||||
class PromiseResolver final : public Runnable {
|
||||
public:
|
||||
explicit PromiseResolver(Promise* aPromise)
|
||||
: Runnable("CookieStoreNotificationWatcherWrapper::PromiseResolver"),
|
||||
mPromise(aPromise),
|
||||
mEventTarget(GetCurrentSerialEventTarget()) {}
|
||||
|
||||
NS_IMETHOD Run() override {
|
||||
mPromise->MaybeResolveWithUndefined();
|
||||
mPromise = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool HasPromise() const { return !!mPromise; }
|
||||
|
||||
private:
|
||||
~PromiseResolver() {
|
||||
NS_ProxyRelease(
|
||||
"CookieStoreNotificationWatcherWrapper::PromiseResolver::mPromise",
|
||||
mEventTarget, mPromise.forget());
|
||||
}
|
||||
|
||||
RefPtr<Promise> mPromise;
|
||||
RefPtr<nsISerialEventTarget> mEventTarget;
|
||||
};
|
||||
|
||||
RefPtr<PromiseResolver> resolver(new PromiseResolver(aPromise));
|
||||
|
||||
RefPtr<ThreadSafeWorkerRef> workerRef;
|
||||
|
||||
if (!NS_IsMainThread()) {
|
||||
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
|
||||
RefPtr<StrongWorkerRef> strongWorkerRef = StrongWorkerRef::Create(
|
||||
workerPrivate, "CookieStoreNotificationWatcher::PromiseResolver",
|
||||
[resolver = RefPtr(resolver)]() { resolver->Run(); });
|
||||
|
||||
workerRef = new ThreadSafeWorkerRef(strongWorkerRef);
|
||||
}
|
||||
|
||||
auto callback = [resolver = RefPtr(resolver),
|
||||
eventTarget = RefPtr(GetCurrentSerialEventTarget()),
|
||||
workerRef = RefPtr(workerRef)] {
|
||||
if (resolver->HasPromise()) {
|
||||
RefPtr<Runnable> runnable(resolver);
|
||||
eventTarget->Dispatch(runnable.forget());
|
||||
}
|
||||
};
|
||||
|
||||
if (!NS_IsMainThread()) {
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
||||
__func__, [self = RefPtr(this), callback, aOperationID] {
|
||||
self->mWatcherOnMainThread->CallbackWhenNotified(aOperationID,
|
||||
callback);
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
if (mWatcherOnMainThread) {
|
||||
mWatcherOnMainThread->CallbackWhenNotified(aOperationID, callback);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
39
dom/cookiestore/CookieStoreNotificationWatcherWrapper.h
Normal file
39
dom/cookiestore/CookieStoreNotificationWatcherWrapper.h
Normal file
@ -0,0 +1,39 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_CookieStoreNotificationWatcherWrapper_h
|
||||
#define mozilla_dom_CookieStoreNotificationWatcherWrapper_h
|
||||
|
||||
#include "mozilla/OriginAttributes.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
class Promise;
|
||||
class CookieStore;
|
||||
class CookieStoreNotificationWatcher;
|
||||
|
||||
class CookieStoreNotificationWatcherWrapper final {
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CookieStoreNotificationWatcherWrapper)
|
||||
|
||||
static already_AddRefed<CookieStoreNotificationWatcherWrapper> Create(
|
||||
CookieStore* aCookieStore);
|
||||
|
||||
void ResolvePromiseWhenNotified(const nsID& aOperationID, Promise* aPromise);
|
||||
void ForgetOperationID(const nsID& aOperationID);
|
||||
|
||||
private:
|
||||
CookieStoreNotificationWatcherWrapper() = default;
|
||||
~CookieStoreNotificationWatcherWrapper();
|
||||
|
||||
void CreateWatcherOnMainThread(bool aPrivateBrowsing);
|
||||
|
||||
RefPtr<CookieStoreNotificationWatcher> mWatcherOnMainThread;
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
||||
#endif /* mozilla_dom_CookieStoreNotificationWatcherWrapper_h */
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "CookieStoreNotifier.h"
|
||||
#include "CookieStore.h"
|
||||
#include "CookieChangeEvent.h"
|
||||
#include "mozilla/net/CookieCommons.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "mozilla/dom/WorkerPrivate.h"
|
||||
@ -192,46 +193,56 @@ CookieStoreNotifier::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
|
||||
bool deletedEvent = action == nsICookieNotification::COOKIE_DELETED;
|
||||
|
||||
mEventTarget->Dispatch(NS_NewRunnableFunction(__func__, [self = RefPtr(this),
|
||||
item, deletedEvent] {
|
||||
if (!self->mCookieStore) {
|
||||
return;
|
||||
}
|
||||
if (mEventTarget->IsOnCurrentThread()) {
|
||||
DispatchEvent(item, deletedEvent);
|
||||
} else {
|
||||
mEventTarget->Dispatch(NS_NewRunnableFunction(
|
||||
__func__, [self = RefPtr(this), item, deletedEvent] {
|
||||
self->DispatchEvent(item, deletedEvent);
|
||||
}));
|
||||
}
|
||||
|
||||
RefPtr<Event> event = deletedEvent
|
||||
? CookieChangeEvent::CreateForDeletedCookie(
|
||||
self->mCookieStore, item)
|
||||
: CookieChangeEvent::CreateForChangedCookie(
|
||||
self->mCookieStore, item);
|
||||
|
||||
if (!event) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
nsCOMPtr<nsPIDOMWindowInner> window =
|
||||
self->mCookieStore->GetOwnerWindow();
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<BrowsingContext> bc = window->GetBrowsingContext();
|
||||
if (!bc) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bc->IsInBFCache() || (window->GetExtantDoc() &&
|
||||
window->GetExtantDoc()->GetBFCacheEntry())) {
|
||||
self->mDelayedDOMEvents.AppendElement(event);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self->mCookieStore->DispatchEvent(*event);
|
||||
}));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void CookieStoreNotifier::DispatchEvent(const CookieListItem& aItem,
|
||||
bool aDeletedEvent) {
|
||||
MOZ_ASSERT(mEventTarget->IsOnCurrentThread());
|
||||
|
||||
if (!mCookieStore) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<Event> event =
|
||||
aDeletedEvent
|
||||
? CookieChangeEvent::CreateForDeletedCookie(mCookieStore, aItem)
|
||||
: CookieChangeEvent::CreateForChangedCookie(mCookieStore, aItem);
|
||||
|
||||
if (!event) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = mCookieStore->GetOwnerWindow();
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<BrowsingContext> bc = window->GetBrowsingContext();
|
||||
if (!bc) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bc->IsInBFCache() ||
|
||||
(window->GetExtantDoc() && window->GetExtantDoc()->GetBFCacheEntry())) {
|
||||
mDelayedDOMEvents.AppendElement(event);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mCookieStore->DispatchEvent(*event);
|
||||
}
|
||||
|
||||
void CookieStoreNotifier::FireDelayedDOMEvents() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "nsIObserver.h"
|
||||
#include "mozilla/OriginAttributes.h"
|
||||
#include "mozilla/MoveOnlyFunction.h"
|
||||
|
||||
class nsISerialEventTarget;
|
||||
|
||||
@ -38,6 +39,8 @@ class CookieStoreNotifier final : public nsIObserver {
|
||||
void AddObserversOnMainThread(bool aPrivateBrowsing);
|
||||
void RemoveObserversOnMainThread(bool aPrivateBrowsing);
|
||||
|
||||
void DispatchEvent(const CookieListItem& aItem, bool aDeletedEvent);
|
||||
|
||||
// Raw pointer because this object is kept alive by this CookieStore object.
|
||||
CookieStore* mCookieStore;
|
||||
|
||||
|
@ -5,23 +5,116 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "CookieStoreParent.h"
|
||||
#include "CookieStoreNotificationWatcher.h"
|
||||
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/ipc/BackgroundParent.h"
|
||||
#include "mozilla/net/CookieCommons.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "nsICookieManager.h"
|
||||
#include "nsProxyRelease.h"
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
namespace {
|
||||
CookieStoreParent::CookieStoreParent() { AssertIsOnBackgroundThread(); }
|
||||
|
||||
void GetRequestHelper(const nsAString& aDomain,
|
||||
const OriginAttributes& aOriginAttributes,
|
||||
bool aMatchName, const nsAString& aName,
|
||||
const nsACString& aPath, bool aOnlyFirstMatch,
|
||||
nsTArray<CookieData>& aResults) {
|
||||
CookieStoreParent::~CookieStoreParent() {
|
||||
AssertIsOnBackgroundThread();
|
||||
CookieStoreNotificationWatcher::ReleaseOnMainThread(
|
||||
mNotificationWatcherOnMainThread.forget());
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult CookieStoreParent::RecvGetRequest(
|
||||
const nsString& aDomain, const OriginAttributes& aOriginAttributes,
|
||||
const bool& aMatchName, const nsString& aName, const nsCString& aPath,
|
||||
const bool& aOnlyFirstMatch, GetRequestResolver&& aResolver) {
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
InvokeAsync(GetMainThreadSerialEventTarget(), __func__,
|
||||
[self = RefPtr(this), aDomain, aOriginAttributes, aMatchName,
|
||||
aName, aPath, aOnlyFirstMatch]() {
|
||||
CopyableTArray<CookieData> results;
|
||||
self->GetRequestOnMainThread(aDomain, aOriginAttributes,
|
||||
aMatchName, aName, aPath,
|
||||
aOnlyFirstMatch, results);
|
||||
return GetRequestPromise::CreateAndResolve(std::move(results),
|
||||
__func__);
|
||||
})
|
||||
->Then(GetCurrentSerialEventTarget(), __func__,
|
||||
[aResolver = std::move(aResolver)](
|
||||
const GetRequestPromise::ResolveOrRejectValue& aResult) {
|
||||
MOZ_ASSERT(aResult.IsResolve());
|
||||
aResolver(aResult.ResolveValue());
|
||||
});
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult CookieStoreParent::RecvSetRequest(
|
||||
const nsString& aDomain, const OriginAttributes& aOriginAttributes,
|
||||
const nsString& aName, const nsString& aValue, const bool& aSession,
|
||||
const int64_t& aExpires, const nsString& aPath, const int32_t& aSameSite,
|
||||
const bool& aPartitioned, const nsID& aOperationID,
|
||||
SetRequestResolver&& aResolver) {
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
InvokeAsync(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[self = RefPtr(this), aDomain, aOriginAttributes, aName, aValue, aSession,
|
||||
aExpires, aPath, aSameSite, aPartitioned, aOperationID]() {
|
||||
bool waitForNotification = self->SetRequestOnMainThread(
|
||||
aDomain, aOriginAttributes, aName, aValue, aSession, aExpires,
|
||||
aPath, aSameSite, aPartitioned, aOperationID);
|
||||
return SetDeleteRequestPromise::CreateAndResolve(waitForNotification,
|
||||
__func__);
|
||||
})
|
||||
->Then(GetCurrentSerialEventTarget(), __func__,
|
||||
[aResolver = std::move(aResolver)](
|
||||
const SetDeleteRequestPromise::ResolveOrRejectValue& aResult) {
|
||||
MOZ_ASSERT(aResult.IsResolve());
|
||||
aResolver(aResult.ResolveValue());
|
||||
});
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult CookieStoreParent::RecvDeleteRequest(
|
||||
const nsString& aDomain, const OriginAttributes& aOriginAttributes,
|
||||
const nsString& aName, const nsString& aPath, const bool& aPartitioned,
|
||||
const nsID& aOperationID, DeleteRequestResolver&& aResolver) {
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
InvokeAsync(GetMainThreadSerialEventTarget(), __func__,
|
||||
[self = RefPtr(this), aDomain, aOriginAttributes, aName, aPath,
|
||||
aPartitioned, aOperationID]() {
|
||||
bool waitForNotification = self->DeleteRequestOnMainThread(
|
||||
aDomain, aOriginAttributes, aName, aPath, aPartitioned,
|
||||
aOperationID);
|
||||
return SetDeleteRequestPromise::CreateAndResolve(
|
||||
waitForNotification, __func__);
|
||||
})
|
||||
->Then(GetCurrentSerialEventTarget(), __func__,
|
||||
[aResolver = std::move(aResolver)](
|
||||
const SetDeleteRequestPromise::ResolveOrRejectValue& aResult) {
|
||||
MOZ_ASSERT(aResult.IsResolve());
|
||||
aResolver(aResult.ResolveValue());
|
||||
});
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult CookieStoreParent::RecvClose() {
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
Unused << Send__delete__(this);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void CookieStoreParent::GetRequestOnMainThread(
|
||||
const nsAString& aDomain, const OriginAttributes& aOriginAttributes,
|
||||
bool aMatchName, const nsAString& aName, const nsACString& aPath,
|
||||
bool aOnlyFirstMatch, nsTArray<CookieData>& aResults) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsCOMPtr<nsICookieManager> service =
|
||||
@ -90,19 +183,30 @@ void GetRequestHelper(const nsAString& aDomain,
|
||||
aResults.SwapElements(list);
|
||||
}
|
||||
|
||||
void SetRequestHelper(const nsAString& aDomain,
|
||||
const OriginAttributes& aOriginAttributes,
|
||||
const nsAString& aName, const nsAString& aValue,
|
||||
bool aSession, int64_t aExpires, const nsAString& aPath,
|
||||
int32_t aSameSite, bool aPartitioned) {
|
||||
bool CookieStoreParent::SetRequestOnMainThread(
|
||||
const nsAString& aDomain, const OriginAttributes& aOriginAttributes,
|
||||
const nsAString& aName, const nsAString& aValue, bool aSession,
|
||||
int64_t aExpires, const nsAString& aPath, int32_t aSameSite,
|
||||
bool aPartitioned, const nsID& aOperationID) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsCOMPtr<nsICookieManager> service =
|
||||
do_GetService(NS_COOKIEMANAGER_CONTRACTID);
|
||||
if (!service) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool notified = false;
|
||||
auto notificationCb = [&]() { notified = true; };
|
||||
|
||||
CookieStoreNotificationWatcher* notificationWatcher =
|
||||
GetOrCreateNotificationWatcherOnMainThread(aOriginAttributes);
|
||||
if (!notificationWatcher) {
|
||||
return false;
|
||||
}
|
||||
|
||||
notificationWatcher->CallbackWhenNotified(aOperationID, notificationCb);
|
||||
|
||||
OriginAttributes attrs(aOriginAttributes);
|
||||
nsresult rv = service->AddNative(
|
||||
NS_ConvertUTF16toUTF8(aDomain), NS_ConvertUTF16toUTF8(aPath),
|
||||
@ -110,22 +214,26 @@ void SetRequestHelper(const nsAString& aDomain,
|
||||
true, // secure
|
||||
false, // mHttpOnly,
|
||||
aSession, aSession ? PR_Now() : aExpires, &attrs, aSameSite,
|
||||
nsICookie::SCHEME_HTTPS, aPartitioned, nullptr);
|
||||
nsICookie::SCHEME_HTTPS, aPartitioned, &aOperationID);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
notificationWatcher->ForgetOperationID(aOperationID);
|
||||
|
||||
return notified;
|
||||
}
|
||||
|
||||
void DeleteRequestHelper(const nsAString& aDomain,
|
||||
const OriginAttributes& aOriginAttributes,
|
||||
const nsAString& aName, const nsAString& aPath,
|
||||
bool aPartitioned) {
|
||||
bool CookieStoreParent::DeleteRequestOnMainThread(
|
||||
const nsAString& aDomain, const OriginAttributes& aOriginAttributes,
|
||||
const nsAString& aName, const nsAString& aPath, bool aPartitioned,
|
||||
const nsID& aOperationID) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsCOMPtr<nsICookieManager> service =
|
||||
do_GetService(NS_COOKIEMANAGER_CONTRACTID);
|
||||
if (!service) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_ConvertUTF16toUTF8 domainUtf8(aDomain);
|
||||
@ -134,7 +242,7 @@ void DeleteRequestHelper(const nsAString& aDomain,
|
||||
nsTArray<RefPtr<nsICookie>> results;
|
||||
nsresult rv = service->GetCookiesFromHostNative(domainUtf8, &attrs, results);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_ConvertUTF16toUTF8 matchName(aName);
|
||||
@ -146,7 +254,7 @@ void DeleteRequestHelper(const nsAString& aDomain,
|
||||
nsAutoCString name;
|
||||
rv = cookie->GetName(name);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!matchName.Equals(name)) {
|
||||
@ -156,7 +264,7 @@ void DeleteRequestHelper(const nsAString& aDomain,
|
||||
nsAutoCString path;
|
||||
rv = cookie->GetPath(path);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!matchPath.IsEmpty() && !matchPath.Equals(path)) {
|
||||
@ -166,97 +274,47 @@ void DeleteRequestHelper(const nsAString& aDomain,
|
||||
bool isPartitioned = false;
|
||||
rv = cookie->GetIsPartitioned(&isPartitioned);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isPartitioned != aPartitioned) continue;
|
||||
|
||||
rv = service->RemoveNative(domainUtf8, matchName, path, &attrs, nullptr);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
bool notified = false;
|
||||
auto notificationCb = [&]() { notified = true; };
|
||||
|
||||
CookieStoreNotificationWatcher* notificationWatcher =
|
||||
GetOrCreateNotificationWatcherOnMainThread(aOriginAttributes);
|
||||
if (!notificationWatcher) {
|
||||
return false;
|
||||
}
|
||||
|
||||
notificationWatcher->CallbackWhenNotified(aOperationID, notificationCb);
|
||||
|
||||
rv = service->RemoveNative(domainUtf8, matchName, path, &attrs,
|
||||
&aOperationID);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
notificationWatcher->ForgetOperationID(aOperationID);
|
||||
|
||||
return notified;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
CookieStoreNotificationWatcher*
|
||||
CookieStoreParent::GetOrCreateNotificationWatcherOnMainThread(
|
||||
const OriginAttributes& aOriginAttributes) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
CookieStoreParent::CookieStoreParent() { AssertIsOnBackgroundThread(); }
|
||||
if (!mNotificationWatcherOnMainThread) {
|
||||
mNotificationWatcherOnMainThread = CookieStoreNotificationWatcher::Create(
|
||||
aOriginAttributes.IsPrivateBrowsing());
|
||||
}
|
||||
|
||||
CookieStoreParent::~CookieStoreParent() { AssertIsOnBackgroundThread(); }
|
||||
|
||||
mozilla::ipc::IPCResult CookieStoreParent::RecvGetRequest(
|
||||
const nsString& aDomain, const OriginAttributes& aOriginAttributes,
|
||||
const bool& aMatchName, const nsString& aName, const nsCString& aPath,
|
||||
const bool& aOnlyFirstMatch, GetRequestResolver&& aResolver) {
|
||||
InvokeAsync(GetMainThreadSerialEventTarget(), __func__,
|
||||
[aDomain, aOriginAttributes, aMatchName, aName, aPath,
|
||||
aOnlyFirstMatch]() {
|
||||
CopyableTArray<CookieData> results;
|
||||
GetRequestHelper(aDomain, aOriginAttributes, aMatchName, aName,
|
||||
aPath, aOnlyFirstMatch, results);
|
||||
return GetRequestPromise::CreateAndResolve(std::move(results),
|
||||
__func__);
|
||||
})
|
||||
->Then(GetCurrentSerialEventTarget(), __func__,
|
||||
[aResolver = std::move(aResolver)](
|
||||
const GetRequestPromise::ResolveOrRejectValue& aResult) {
|
||||
MOZ_ASSERT(aResult.IsResolve());
|
||||
aResolver(aResult.ResolveValue());
|
||||
});
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult CookieStoreParent::RecvSetRequest(
|
||||
const nsString& aDomain, const OriginAttributes& aOriginAttributes,
|
||||
const nsString& aName, const nsString& aValue, const bool& aSession,
|
||||
const int64_t& aExpires, const nsString& aPath, const int32_t& aSameSite,
|
||||
const bool& aPartitioned, SetRequestResolver&& aResolver) {
|
||||
InvokeAsync(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[aDomain, aOriginAttributes, aName, aValue, aSession, aExpires, aPath,
|
||||
aSameSite, aPartitioned]() {
|
||||
SetRequestHelper(aDomain, aOriginAttributes, aName, aValue, aSession,
|
||||
aExpires, aPath, aSameSite, aPartitioned);
|
||||
return SetDeleteRequestPromise::CreateAndResolve(true, __func__);
|
||||
})
|
||||
->Then(GetCurrentSerialEventTarget(), __func__,
|
||||
[aResolver = std::move(aResolver)](
|
||||
const SetDeleteRequestPromise::ResolveOrRejectValue& aResult) {
|
||||
MOZ_ASSERT(aResult.IsResolve());
|
||||
aResolver(aResult.ResolveValue());
|
||||
});
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult CookieStoreParent::RecvDeleteRequest(
|
||||
const nsString& aDomain, const OriginAttributes& aOriginAttributes,
|
||||
const nsString& aName, const nsString& aPath, const bool& aPartitioned,
|
||||
DeleteRequestResolver&& aResolver) {
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
InvokeAsync(GetMainThreadSerialEventTarget(), __func__,
|
||||
[aDomain, aOriginAttributes, aName, aPath, aPartitioned]() {
|
||||
DeleteRequestHelper(aDomain, aOriginAttributes, aName, aPath,
|
||||
aPartitioned);
|
||||
return SetDeleteRequestPromise::CreateAndResolve(true,
|
||||
__func__);
|
||||
})
|
||||
->Then(GetCurrentSerialEventTarget(), __func__,
|
||||
[aResolver = std::move(aResolver)](
|
||||
const SetDeleteRequestPromise::ResolveOrRejectValue& aResult) {
|
||||
MOZ_ASSERT(aResult.IsResolve());
|
||||
aResolver(aResult.ResolveValue());
|
||||
});
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult CookieStoreParent::RecvClose() {
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
Unused << Send__delete__(this);
|
||||
return IPC_OK();
|
||||
return mNotificationWatcherOnMainThread;
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
class CookieStoreService;
|
||||
class CookieStoreNotificationWatcher;
|
||||
|
||||
class CookieStoreParent final : public PCookieStoreParent {
|
||||
friend class PCookieStoreParent;
|
||||
@ -22,7 +22,7 @@ class CookieStoreParent final : public PCookieStoreParent {
|
||||
MozPromise<CopyableTArray<CookieData>, nsresult, true>;
|
||||
using SetDeleteRequestPromise = MozPromise<bool, nsresult, true>;
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(CookieStoreParent)
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CookieStoreParent)
|
||||
|
||||
CookieStoreParent();
|
||||
|
||||
@ -38,14 +38,42 @@ class CookieStoreParent final : public PCookieStoreParent {
|
||||
const nsString& aDomain, const OriginAttributes& aOriginAttributes,
|
||||
const nsString& aName, const nsString& aValue, const bool& aSession,
|
||||
const int64_t& aExpires, const nsString& aPath, const int32_t& aSameSite,
|
||||
const bool& aPartitioned, SetRequestResolver&& aResolver);
|
||||
const bool& aPartitioned, const nsID& aOperationID,
|
||||
SetRequestResolver&& aResolver);
|
||||
|
||||
mozilla::ipc::IPCResult RecvDeleteRequest(
|
||||
const nsString& aDomain, const OriginAttributes& aOriginAttributes,
|
||||
const nsString& aName, const nsString& aPath, const bool& aPartitioned,
|
||||
DeleteRequestResolver&& aResolver);
|
||||
const nsID& aOperationID, DeleteRequestResolver&& aResolver);
|
||||
|
||||
mozilla::ipc::IPCResult RecvClose();
|
||||
|
||||
void GetRequestOnMainThread(const nsAString& aDomain,
|
||||
const OriginAttributes& aOriginAttributes,
|
||||
bool aMatchName, const nsAString& aName,
|
||||
const nsACString& aPath, bool aOnlyFirstMatch,
|
||||
nsTArray<CookieData>& aResults);
|
||||
|
||||
// Returns true if a cookie notification has been generated while completing
|
||||
// the operation.
|
||||
bool SetRequestOnMainThread(const nsAString& aDomain,
|
||||
const OriginAttributes& aOriginAttributes,
|
||||
const nsAString& aName, const nsAString& aValue,
|
||||
bool aSession, int64_t aExpires,
|
||||
const nsAString& aPath, int32_t aSameSite,
|
||||
bool aPartitioned, const nsID& aOperationID);
|
||||
|
||||
// Returns true if a cookie notification has been generated while completing
|
||||
// the operation.
|
||||
bool DeleteRequestOnMainThread(const nsAString& aDomain,
|
||||
const OriginAttributes& aOriginAttributes,
|
||||
const nsAString& aName, const nsAString& aPath,
|
||||
bool aPartitioned, const nsID& aOperationID);
|
||||
|
||||
CookieStoreNotificationWatcher* GetOrCreateNotificationWatcherOnMainThread(
|
||||
const OriginAttributes& aOriginAttributes);
|
||||
|
||||
RefPtr<CookieStoreNotificationWatcher> mNotificationWatcherOnMainThread;
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
@ -6,6 +6,7 @@ include protocol PBackground;
|
||||
|
||||
using mozilla::OriginAttributes from "mozilla/ipc/BackgroundUtils.h";
|
||||
using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
|
||||
using struct nsID from "nsID.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -44,13 +45,15 @@ parent:
|
||||
int64_t expires,
|
||||
nsString path,
|
||||
int32_t sameSite,
|
||||
bool partitioned) returns (bool v);
|
||||
bool partitioned,
|
||||
nsID operationId) returns (bool waitForNotification);
|
||||
|
||||
async DeleteRequest(nsString domain,
|
||||
OriginAttributes attrs,
|
||||
nsString name,
|
||||
nsString path,
|
||||
bool partitioned) returns (bool v);
|
||||
bool partitioned,
|
||||
nsID operationID) returns (bool waitForNotification);
|
||||
|
||||
async Close();
|
||||
|
||||
|
@ -16,6 +16,8 @@ UNIFIED_SOURCES += [
|
||||
"CookieChangeEvent.cpp",
|
||||
"CookieStore.cpp",
|
||||
"CookieStoreChild.cpp",
|
||||
"CookieStoreNotificationWatcher.cpp",
|
||||
"CookieStoreNotificationWatcherWrapper.cpp",
|
||||
"CookieStoreNotifier.cpp",
|
||||
"CookieStoreParent.cpp",
|
||||
]
|
||||
|
@ -3830,6 +3830,8 @@ ContentParent::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
return NS_OK;
|
||||
}
|
||||
auto* cs = static_cast<CookieServiceParent*>(csParent);
|
||||
MOZ_ASSERT(mCookieInContentListCache.IsEmpty());
|
||||
|
||||
if (action == nsICookieNotification::COOKIES_BATCH_DELETED) {
|
||||
nsCOMPtr<nsIArray> cookieList;
|
||||
DebugOnly<nsresult> rv =
|
||||
@ -6124,6 +6126,17 @@ nsresult ContentParent::TransmitPermissionsForPrincipal(
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void ContentParent::AddPrincipalToCookieInProcessCache(
|
||||
nsIPrincipal* aPrincipal) {
|
||||
MOZ_ASSERT(aPrincipal);
|
||||
mCookieInContentListCache.AppendElement(aPrincipal);
|
||||
}
|
||||
|
||||
void ContentParent::TakeCookieInProcessCache(
|
||||
nsTArray<nsCOMPtr<nsIPrincipal>>& aList) {
|
||||
aList.SwapElements(mCookieInContentListCache);
|
||||
}
|
||||
|
||||
void ContentParent::TransmitBlobURLsForPrincipal(nsIPrincipal* aPrincipal) {
|
||||
// If we're already broadcasting BlobURLs with this principal, we don't need
|
||||
// to send them here.
|
||||
|
@ -629,6 +629,12 @@ class ContentParent final : public PContentParent,
|
||||
// to this content process forever.
|
||||
void TransmitBlobURLsForPrincipal(nsIPrincipal* aPrincipal);
|
||||
|
||||
// Update a cache list of allowed domains to store cookies for the current
|
||||
// process. This method is called when PCookieServiceParent actor is not
|
||||
// available yet.
|
||||
void AddPrincipalToCookieInProcessCache(nsIPrincipal* aPrincipal);
|
||||
void TakeCookieInProcessCache(nsTArray<nsCOMPtr<nsIPrincipal>>& aList);
|
||||
|
||||
nsresult TransmitPermissionsForPrincipal(nsIPrincipal* aPrincipal);
|
||||
|
||||
// Whenever receiving a Principal we need to validate that Principal case
|
||||
@ -1567,6 +1573,8 @@ class ContentParent final : public PContentParent,
|
||||
|
||||
nsTArray<nsCString> mBlobURLs;
|
||||
|
||||
nsTArray<nsCOMPtr<nsIPrincipal>> mCookieInContentListCache;
|
||||
|
||||
// This is intended to be a memory and time efficient means of determining
|
||||
// whether an origin has ever existed in a process so that Blob URL broadcast
|
||||
// doesn't need to transmit every Blob URL to every content process. False
|
||||
|
@ -17,6 +17,9 @@
|
||||
#include "mozilla/ipc/BackgroundParent.h"
|
||||
#include "mozilla/ipc/BackgroundUtils.h"
|
||||
#include "mozilla/ipc/PBackgroundParent.h"
|
||||
#include "mozilla/net/CookieServiceParent.h"
|
||||
#include "mozilla/net/NeckoParent.h"
|
||||
#include "mozilla/net/CookieServiceParent.h"
|
||||
#include "mozilla/StaticPrefs_extensions.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsImportModule.h"
|
||||
@ -36,6 +39,7 @@ mozilla::LazyLogModule gRemoteWorkerManagerLog("RemoteWorkerManager");
|
||||
namespace mozilla {
|
||||
|
||||
using namespace ipc;
|
||||
using namespace net;
|
||||
|
||||
namespace dom {
|
||||
|
||||
@ -50,7 +54,7 @@ bool IsServiceWorker(const RemoteWorkerData& aData) {
|
||||
OptionalServiceWorkerData::TServiceWorkerData;
|
||||
}
|
||||
|
||||
void TransmitPermissionsAndBlobURLsForPrincipalInfo(
|
||||
void TransmitPermissionsAndCookiesAndBlobURLsForPrincipalInfo(
|
||||
ContentParent* aContentParent, const PrincipalInfo& aPrincipalInfo) {
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aContentParent);
|
||||
@ -67,6 +71,25 @@ void TransmitPermissionsAndBlobURLsForPrincipalInfo(
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
aContentParent->TransmitPermissionsForPrincipal(principal));
|
||||
|
||||
CookieServiceParent* cs = nullptr;
|
||||
|
||||
PNeckoParent* neckoParent =
|
||||
LoneManagedOrNullAsserts(aContentParent->ManagedPNeckoParent());
|
||||
if (neckoParent) {
|
||||
PCookieServiceParent* csParent =
|
||||
LoneManagedOrNullAsserts(neckoParent->ManagedPCookieServiceParent());
|
||||
if (csParent) {
|
||||
cs = static_cast<CookieServiceParent*>(csParent);
|
||||
}
|
||||
}
|
||||
|
||||
if (cs) {
|
||||
nsCOMPtr<nsIURI> uri = principal->GetURI();
|
||||
cs->UpdateCookieInContentList(uri, principal->OriginAttributesRef());
|
||||
} else {
|
||||
aContentParent->AddPrincipalToCookieInProcessCache(principal);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@ -313,8 +336,8 @@ void RemoteWorkerManager::LaunchInternal(
|
||||
AssertIsOnMainThread();
|
||||
if (RefPtr<ContentParent> contentParent =
|
||||
contentHandle->GetContentParent()) {
|
||||
TransmitPermissionsAndBlobURLsForPrincipalInfo(contentParent,
|
||||
principalInfo);
|
||||
TransmitPermissionsAndCookiesAndBlobURLsForPrincipalInfo(
|
||||
contentParent, principalInfo);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -6,9 +6,9 @@
|
||||
#include "CookieCommons.h"
|
||||
#include "CookieLogging.h"
|
||||
#include "CookieServiceParent.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/net/CookieService.h"
|
||||
#include "mozilla/net/CookieServiceParent.h"
|
||||
#include "mozilla/net/NeckoParent.h"
|
||||
|
||||
#include "mozilla/ipc/URIUtils.h"
|
||||
#include "mozilla/StoragePrincipalHelper.h"
|
||||
@ -25,7 +25,9 @@ using namespace mozilla::ipc;
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
CookieServiceParent::CookieServiceParent() {
|
||||
CookieServiceParent::CookieServiceParent(dom::ContentParent* aContentParent) {
|
||||
MOZ_ASSERT(aContentParent);
|
||||
|
||||
// Instantiate the cookieservice via the service manager, so it sticks around
|
||||
// until shutdown.
|
||||
nsCOMPtr<nsICookieService> cs = do_GetService(NS_COOKIESERVICE_CONTRACTID);
|
||||
@ -38,6 +40,14 @@ CookieServiceParent::CookieServiceParent() {
|
||||
MOZ_ALWAYS_TRUE(mTLDService);
|
||||
|
||||
mProcessingCookie = false;
|
||||
|
||||
nsTArray<nsCOMPtr<nsIPrincipal>> list;
|
||||
aContentParent->TakeCookieInProcessCache(list);
|
||||
|
||||
for (nsIPrincipal* principal : list) {
|
||||
nsCOMPtr<nsIURI> uri = principal->GetURI();
|
||||
UpdateCookieInContentList(uri, principal->OriginAttributesRef());
|
||||
}
|
||||
}
|
||||
|
||||
void CookieServiceParent::RemoveBatchDeletedCookies(nsIArray* aCookieList) {
|
||||
|
@ -13,7 +13,11 @@ class nsIArray;
|
||||
class nsICookie;
|
||||
namespace mozilla {
|
||||
class OriginAttributes;
|
||||
}
|
||||
|
||||
namespace dom {
|
||||
class ContentParent;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
class nsIEffectiveTLDService;
|
||||
|
||||
@ -27,7 +31,7 @@ class CookieServiceParent : public PCookieServiceParent {
|
||||
friend class PCookieServiceParent;
|
||||
|
||||
public:
|
||||
CookieServiceParent();
|
||||
explicit CookieServiceParent(dom::ContentParent* aContentParent);
|
||||
virtual ~CookieServiceParent() = default;
|
||||
|
||||
void TrackCookieLoad(nsIChannel* aChannel);
|
||||
|
@ -287,7 +287,7 @@ mozilla::ipc::IPCResult NeckoParent::RecvPDocumentChannelConstructor(
|
||||
}
|
||||
|
||||
PCookieServiceParent* NeckoParent::AllocPCookieServiceParent() {
|
||||
return new CookieServiceParent();
|
||||
return new CookieServiceParent(static_cast<ContentParent*>(Manager()));
|
||||
}
|
||||
|
||||
bool NeckoParent::DeallocPCookieServiceParent(PCookieServiceParent* cs) {
|
||||
|
Loading…
Reference in New Issue
Block a user