diff --git a/dom/cookiestore/CookieStore.cpp b/dom/cookiestore/CookieStore.cpp index c187771e1831..8b7bf1c1dea4 100644 --- a/dom/cookiestore/CookieStore.cpp +++ b/dom/cookiestore/CookieStore.cpp @@ -16,6 +16,7 @@ #include "mozilla/ipc/BackgroundChild.h" #include "mozilla/ipc/PBackgroundChild.h" #include "mozilla/net/CookieCommons.h" +#include "mozilla/net/NeckoChannelParams.h" #include "mozilla/StorageAccess.h" #include "nsICookie.h" #include "nsIGlobalObject.h" @@ -216,16 +217,11 @@ bool ValidateCookieNamePrefix(const nsAString& aName, const nsAString& aValue, return true; } -void CookieDataToItem(const CookieData& aData, CookieListItem* aItem) { - aItem->mName.Construct(aData.name()); - aItem->mValue.Construct(aData.value()); -} - -void CookieDataToList(const nsTArray& aData, - nsTArray& aResult) { - for (const CookieData& data : aData) { +void CookieStructToList(const nsTArray& aData, + nsTArray& aResult) { + for (const CookieStruct& data : aData) { CookieListItem* item = aResult.AppendElement(); - CookieDataToItem(data, item); + CookieStore::CookieStructToItem(data, item); } } @@ -783,7 +779,7 @@ already_AddRefed CookieStore::GetInternal( } nsTArray list; - CookieDataToList(aResult.ResolveValue(), list); + CookieStructToList(aResult.ResolveValue(), list); if (!aOnlyTheFirstMatch) { promise->MaybeResolve(list); @@ -820,4 +816,44 @@ Document* CookieStore::MaybeGetDocument() const { return nullptr; } +// static +void CookieStore::CookieStructToItem(const CookieStruct& aData, + CookieListItem* aItem) { + aItem->mName.Construct(aData.name()); + aItem->mValue.Construct(aData.value()); + aItem->mPath.Construct(aData.path()); + + if (aData.host().IsEmpty() || aData.host()[0] != '.') { + aItem->mDomain.Construct(VoidCString()); + } else { + aItem->mDomain.Construct(nsDependentCSubstring(aData.host(), 1)); + } + + if (!aData.isSession()) { + aItem->mExpires.Construct(aData.expiry() * PR_MSEC_PER_SEC); + } else { + aItem->mExpires.Construct(nullptr); + } + + aItem->mSecure.Construct(aData.isSecure()); + + CookieSameSite sameSite = CookieSameSite::None; + switch (aData.sameSite()) { + case nsICookie::SAMESITE_STRICT: + sameSite = CookieSameSite::Strict; + break; + + case nsICookie::SAMESITE_LAX: + sameSite = CookieSameSite::Lax; + break; + + default: + // FIXME: lax by default? + break; + } + + aItem->mSameSite.Construct(sameSite); + aItem->mPartitioned.Construct(aData.isPartitioned()); +} + } // namespace mozilla::dom diff --git a/dom/cookiestore/CookieStore.h b/dom/cookiestore/CookieStore.h index 244889d21728..94b95c0de6e7 100644 --- a/dom/cookiestore/CookieStore.h +++ b/dom/cookiestore/CookieStore.h @@ -13,9 +13,12 @@ class nsIGlobalObject; +namespace mozilla::net { +class CookieStruct; +} + namespace mozilla::dom { -class CookieData; class CookieStoreChild; class CookieStoreNotificationWatcherWrapper; class CookieStoreNotifier; @@ -57,6 +60,9 @@ class CookieStore final : public DOMEventTargetHelper { IMPL_EVENT_HANDLER(change); + static void CookieStructToItem(const net::CookieStruct& aData, + CookieListItem* aItem); + private: explicit CookieStore(nsIGlobalObject* aGlobal); ~CookieStore(); diff --git a/dom/cookiestore/CookieStoreNotifier.cpp b/dom/cookiestore/CookieStoreNotifier.cpp index 918e04b4ff9a..2fda55a20750 100644 --- a/dom/cookiestore/CookieStoreNotifier.cpp +++ b/dom/cookiestore/CookieStoreNotifier.cpp @@ -7,6 +7,7 @@ #include "CookieStoreNotifier.h" #include "CookieStore.h" #include "CookieChangeEvent.h" +#include "mozilla/net/Cookie.h" #include "mozilla/net/CookieCommons.h" #include "mozilla/dom/Document.h" #include "mozilla/dom/WorkerPrivate.h" @@ -140,23 +141,10 @@ CookieStoreNotifier::Observe(nsISupports* aSubject, const char* aTopic, } CookieListItem item; + CookieStore::CookieStructToItem(net::Cookie::Cast(cookie)->ToIPC(), &item); - nsAutoCString name; - rv = cookie->GetName(name); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - item.mName.Construct(NS_ConvertUTF8toUTF16(name)); - - if (action != nsICookieNotification::COOKIE_DELETED) { - nsAutoCString value; - rv = cookie->GetValue(value); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - item.mValue.Construct(NS_ConvertUTF8toUTF16(value)); + if (action == nsICookieNotification::COOKIE_DELETED) { + item.mValue.Reset(); } bool deletedEvent = action == nsICookieNotification::COOKIE_DELETED; diff --git a/dom/cookiestore/CookieStoreParent.cpp b/dom/cookiestore/CookieStoreParent.cpp index 6580a0614919..b646c338ff35 100644 --- a/dom/cookiestore/CookieStoreParent.cpp +++ b/dom/cookiestore/CookieStoreParent.cpp @@ -86,7 +86,7 @@ mozilla::ipc::IPCResult CookieStoreParent::RecvGetRequest( aPartitionedOriginAttributes, aThirdPartyContext, aPartitionForeign, aUsingStorageAccess, aIsOn3PCBExceptionList, aMatchName, aName, aPath, aOnlyFirstMatch]() { - CopyableTArray results; + CopyableTArray results; self->GetRequestOnMainThread( uri, aOriginAttributes, aPartitionedOriginAttributes, aThirdPartyContext, aPartitionForeign, aUsingStorageAccess, @@ -269,7 +269,7 @@ void CookieStoreParent::GetRequestOnMainThread( bool aThirdPartyContext, bool aPartitionForeign, bool aUsingStorageAccess, bool aIsOn3PCBExceptionList, bool aMatchName, const nsAString& aName, const nsACString& aPath, bool aOnlyFirstMatch, - nsTArray& aResults) { + nsTArray& aResults) { nsresult rv; MOZ_ASSERT(NS_IsMainThread()); @@ -303,7 +303,7 @@ void CookieStoreParent::GetRequestOnMainThread( attrsList.AppendElement(aPartitionedOriginAttributes.value()); } - nsTArray list; + nsTArray list; for (const OriginAttributes& attrs : attrsList) { nsTArray> cookies; @@ -332,9 +332,7 @@ void CookieStoreParent::GetRequestOnMainThread( continue; } - CookieData* data = list.AppendElement(); - data->name() = NS_ConvertUTF8toUTF16(cookie->Name()); - data->value() = NS_ConvertUTF8toUTF16(cookie->Value()); + list.AppendElement(cookie->ToIPC()); if (aOnlyFirstMatch) { break; diff --git a/dom/cookiestore/CookieStoreParent.h b/dom/cookiestore/CookieStoreParent.h index f1bdd07c6cd6..7af6b1bedc80 100644 --- a/dom/cookiestore/CookieStoreParent.h +++ b/dom/cookiestore/CookieStoreParent.h @@ -20,7 +20,7 @@ class CookieStoreParent final : public PCookieStoreParent { public: using GetRequestPromise = - MozPromise, nsresult, true>; + MozPromise, nsresult, true>; using SetDeleteRequestPromise = MozPromise; using GetSubscriptionsRequestPromise = MozPromise, nsresult, true>; @@ -75,7 +75,7 @@ class CookieStoreParent final : public PCookieStoreParent { bool aThirdPartyContext, bool aPartitionForeign, bool aUsingStorageAccess, bool aIsOn3PCBExceptionList, bool aMatchName, const nsAString& aName, const nsACString& aPath, bool aOnlyFirstMatch, - nsTArray& aResults); + nsTArray& aResults); // Returns true if a cookie notification has been generated while completing // the operation. diff --git a/dom/cookiestore/CookieStoreSubscriptionService.cpp b/dom/cookiestore/CookieStoreSubscriptionService.cpp index 8c4c60ac1a98..1508c19b95dc 100644 --- a/dom/cookiestore/CookieStoreSubscriptionService.cpp +++ b/dom/cookiestore/CookieStoreSubscriptionService.cpp @@ -344,8 +344,8 @@ CookieStoreSubscriptionService::Observe(nsISupports* aSubject, } rv = swm->SendCookieChangeEvent(principalInfo.attrs(), - data.mRegistration.scope(), name, value, - deleteEvent); + data.mRegistration.scope(), + cookie->AsCookie().ToIPC(), deleteEvent); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } diff --git a/dom/cookiestore/PCookieStore.ipdl b/dom/cookiestore/PCookieStore.ipdl index e87b10b2064b..ea6defda3291 100644 --- a/dom/cookiestore/PCookieStore.ipdl +++ b/dom/cookiestore/PCookieStore.ipdl @@ -4,6 +4,7 @@ include protocol PBackground; include PBackgroundSharedTypes; +include NeckoChannelParams; using mozilla::OriginAttributes from "mozilla/ipc/BackgroundUtils.h"; using struct mozilla::void_t from "ipc/IPCMessageUtils.h"; @@ -13,15 +14,9 @@ using struct nsID from "nsID.h"; namespace mozilla { namespace dom { -struct CookieData +union MaybeCookieStruct { - nsString name; - nsString value; -}; - -union MaybeCookieData -{ - CookieData; + CookieStruct; void_t; }; @@ -48,7 +43,7 @@ parent: bool matchName, nsString name, nsCString path, - bool onlyFirstMatch) returns (CookieData[] data); + bool onlyFirstMatch) returns (CookieStruct[] data); async SetRequest(nullable nsIURI cookieURI, OriginAttributes attrs, diff --git a/dom/serviceworkers/ServiceWorkerManager.cpp b/dom/serviceworkers/ServiceWorkerManager.cpp index 2d315c9842ea..101dc1fa87c0 100644 --- a/dom/serviceworkers/ServiceWorkerManager.cpp +++ b/dom/serviceworkers/ServiceWorkerManager.cpp @@ -1098,8 +1098,7 @@ ServiceWorkerManager::SendPushEvent(const nsACString& aOriginAttributes, nsresult ServiceWorkerManager::SendCookieChangeEvent( const OriginAttributes& aOriginAttributes, const nsACString& aScope, - const nsAString& aCookieName, const nsAString& aCookieValue, - bool aCookieDeleted) { + const net::CookieStruct& aCookie, bool aCookieDeleted) { nsCOMPtr principal; MOZ_TRY_VAR(principal, ScopeToPrincipal(aScope, aOriginAttributes)); @@ -1117,7 +1116,7 @@ nsresult ServiceWorkerManager::SendCookieChangeEvent( } return serviceWorker->WorkerPrivate()->SendCookieChangeEvent( - aCookieName, aCookieValue, aCookieDeleted, registration); + aCookie, aCookieDeleted, registration); } nsresult ServiceWorkerManager::SendPushEvent( diff --git a/dom/serviceworkers/ServiceWorkerManager.h b/dom/serviceworkers/ServiceWorkerManager.h index da0e1cce1566..cdd876a4c15a 100644 --- a/dom/serviceworkers/ServiceWorkerManager.h +++ b/dom/serviceworkers/ServiceWorkerManager.h @@ -43,6 +43,10 @@ namespace ipc { class PrincipalInfo; } // namespace ipc +namespace net { +class CookieStruct; +} + namespace dom { class ContentParent; @@ -261,8 +265,7 @@ class ServiceWorkerManager final : public nsIServiceWorkerManager, nsresult SendCookieChangeEvent(const OriginAttributes& aOriginAttributes, const nsACString& aScope, - const nsAString& aCookieName, - const nsAString& aCookieValue, + const net::CookieStruct& aCookie, bool aCookieDeleted); nsresult SendPushEvent(const nsACString& aOriginAttributes, diff --git a/dom/serviceworkers/ServiceWorkerOp.cpp b/dom/serviceworkers/ServiceWorkerOp.cpp index c6acab9dd22b..9f7157e396f0 100644 --- a/dom/serviceworkers/ServiceWorkerOp.cpp +++ b/dom/serviceworkers/ServiceWorkerOp.cpp @@ -12,6 +12,7 @@ #include "js/Exception.h" // JS::ExceptionStack, JS::StealPendingExceptionStack #include "jsapi.h" +#include "mozilla/dom/CookieStore.h" #include "mozilla/dom/PushSubscriptionChangeEvent.h" #include "mozilla/dom/PushSubscriptionChangeEventBinding.h" #include "nsCOMPtr.h" @@ -715,8 +716,7 @@ class CookieChangeEventOp final : public ExtendableEventOp { mArgs.get_ServiceWorkerCookieChangeEventOpArgs(); CookieListItem item; - item.mName.Construct(); - item.mName.Value() = args.name(); + CookieStore::CookieStructToItem(args.cookie(), &item); GlobalObject globalObj(aCx, aWorkerPrivate->GlobalScope()->GetWrapper()); nsCOMPtr eventTarget = @@ -725,14 +725,12 @@ class CookieChangeEventOp final : public ExtendableEventOp { RefPtr event; - if (!args.deleted()) { - item.mValue.Construct(); - item.mValue.Value() = args.value(); - - event = ExtendableCookieChangeEvent::CreateForChangedCookie(eventTarget, + if (args.deleted()) { + item.mValue.Reset(); + event = ExtendableCookieChangeEvent::CreateForDeletedCookie(eventTarget, item); } else { - event = ExtendableCookieChangeEvent::CreateForDeletedCookie(eventTarget, + event = ExtendableCookieChangeEvent::CreateForChangedCookie(eventTarget, item); } diff --git a/dom/serviceworkers/ServiceWorkerOpArgs.ipdlh b/dom/serviceworkers/ServiceWorkerOpArgs.ipdlh index a518dd90c4c6..bb5e22a245bb 100644 --- a/dom/serviceworkers/ServiceWorkerOpArgs.ipdlh +++ b/dom/serviceworkers/ServiceWorkerOpArgs.ipdlh @@ -5,6 +5,7 @@ include ClientIPCTypes; include DOMTypes; include FetchTypes; +include NeckoChannelParams; include "mozilla/dom/ServiceWorkerIPCUtils.h"; @@ -32,8 +33,7 @@ struct ServiceWorkerLifeCycleEventOpArgs { }; struct ServiceWorkerCookieChangeEventOpArgs { - nsString name; - nsString value; + CookieStruct cookie; bool deleted; }; diff --git a/dom/serviceworkers/ServiceWorkerPrivate.cpp b/dom/serviceworkers/ServiceWorkerPrivate.cpp index 4c5136cac44c..926c857742a2 100644 --- a/dom/serviceworkers/ServiceWorkerPrivate.cpp +++ b/dom/serviceworkers/ServiceWorkerPrivate.cpp @@ -937,15 +937,14 @@ nsresult ServiceWorkerPrivate::SendLifeCycleEvent( } nsresult ServiceWorkerPrivate::SendCookieChangeEvent( - const nsAString& aCookieName, const nsAString& aCookieValue, - bool aCookieDeleted, RefPtr aRegistration) { + const net::CookieStruct& aCookie, bool aCookieDeleted, + RefPtr aRegistration) { AssertIsOnMainThread(); MOZ_ASSERT(mInfo); MOZ_ASSERT(aRegistration); ServiceWorkerCookieChangeEventOpArgs args; - args.name() = aCookieName; - args.value() = aCookieValue; + args.cookie() = aCookie; args.deleted() = aCookieDeleted; if (mInfo->State() == ServiceWorkerState::Activating) { diff --git a/dom/serviceworkers/ServiceWorkerPrivate.h b/dom/serviceworkers/ServiceWorkerPrivate.h index 269aa875fb4d..b4b0db74f45f 100644 --- a/dom/serviceworkers/ServiceWorkerPrivate.h +++ b/dom/serviceworkers/ServiceWorkerPrivate.h @@ -40,6 +40,10 @@ class Maybe; class JSObjectHolder; +namespace net { +class CookieStruct; +} + namespace dom { class PostMessageSource; @@ -106,8 +110,8 @@ class ServiceWorkerPrivate final : public RemoteWorkerObserver { const RefPtr& aCallback); nsresult SendCookieChangeEvent( - const nsAString& aCookieName, const nsAString& aCookieValue, - bool aCookieDeleted, RefPtr aRegistration); + const net::CookieStruct& aCookie, bool aCookieDeleted, + RefPtr aRegistration); nsresult SendPushEvent(const nsAString& aMessageId, const Maybe>& aData, diff --git a/dom/webidl/CookieStore.webidl b/dom/webidl/CookieStore.webidl index f35d20a0bd17..b98f0d22fb72 100644 --- a/dom/webidl/CookieStore.webidl +++ b/dom/webidl/CookieStore.webidl @@ -69,28 +69,28 @@ dictionary CookieStoreDeleteOptions { }; dictionary CookieListItem { - USVString name; - USVString value; + /* UTF8String semantics match USVString */ - /* Bug 1475599 - We decide to do not implement the entire cookie-store spec. - * Instead, we implement only the subset that is compatible with document.cookie */ - // USVString? domain; - // USVString path; - // DOMHighResTimeStamp? expires; - // boolean secure; - // CookieSameSite sameSite; - // boolean partitioned; + UTF8String name; + UTF8String value; + + [Pref="dom.cookieStore.extra.enabled"] + UTF8String path; + + [Pref="dom.cookieStore.extra.enabled"] + UTF8String? domain; + + [Pref="dom.cookieStore.extra.enabled"] + DOMHighResTimeStamp? expires; + + [Pref="dom.cookieStore.extra.enabled"] + boolean secure; + + [Pref="dom.cookieStore.extra.enabled"] + CookieSameSite sameSite; + + [Pref="dom.cookieStore.extra.enabled"] + boolean partitioned; }; typedef sequence CookieList; - -/* Bug 1475599 - We decide to do not implement the entire cookie-store spec. - * Instead, we implement only the subset that is compatible with document.cookie -[Exposed=(ServiceWorker,Window), - SecureContext] -interface CookieStoreManager { - Promise subscribe(sequence subscriptions); - Promise> getSubscriptions(); - Promise unsubscribe(sequence subscriptions); -}; -*/ diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml index 50883c437dad..b3dcb9a985f4 100644 --- a/modules/libpref/init/StaticPrefList.yaml +++ b/modules/libpref/init/StaticPrefList.yaml @@ -2576,6 +2576,12 @@ value: true mirror: always +# Disable extra cookie-store properties +- name: dom.cookieStore.extra.enabled + type: RelaxedAtomicBool + value: @IS_NIGHTLY_BUILD@ + mirror: always + # Is support for CSSPseudoElement enabled? - name: dom.css_pseudo_element.enabled type: bool diff --git a/testing/web-platform/meta/cookie-store/__dir__.ini b/testing/web-platform/meta/cookie-store/__dir__.ini index 421a141c7c2a..a7170f9adb29 100644 --- a/testing/web-platform/meta/cookie-store/__dir__.ini +++ b/testing/web-platform/meta/cookie-store/__dir__.ini @@ -1,4 +1,4 @@ # https://bugzilla.mozilla.org/show_bug.cgi?id=1475599 -prefs: [dom.cookieStore.enabled:true,dom.cookieStore.manager.enabled:true] +prefs: [dom.cookieStore.enabled:true,dom.cookieStore.manager.enabled:true,dom.cookieStore.extra.enabled:true] implementation-status: backlog lsan-allowed: [Alloc, Malloc, Then, mozilla::BasePrincipal::CreateContentPrincipal, mozilla::dom::DocGroup::Create, mozilla::dom::ServiceWorkerJobQueue::RunJob, mozilla::dom::ServiceWorkerManager::Unregister, mozilla::dom::ServiceWorkerRegistrationMainThread::Unregister, mozilla::dom::UnregisterCallback::UnregisterCallback, mozilla::net::nsStandardURL::TemplatedMutator, operator] diff --git a/testing/web-platform/meta/cookie-store/cookieListItem_attributes.https.any.js.ini b/testing/web-platform/meta/cookie-store/cookieListItem_attributes.https.any.js.ini deleted file mode 100644 index 61bcdfad86fb..000000000000 --- a/testing/web-platform/meta/cookie-store/cookieListItem_attributes.https.any.js.ini +++ /dev/null @@ -1,70 +0,0 @@ -[cookieListItem_attributes.https.any.serviceworker.html] - expected: - if os == "win": [OK, TIMEOUT] - [CookieListItem - cookieStore.set defaults with positional name and value] - expected: FAIL - - [CookieListItem - cookieStore.set defaults with name and value in options] - expected: FAIL - - [CookieListItem - cookieStore.set with expires set to a timestamp 10 years in the future] - expected: FAIL - - [CookieListItem - cookieStore.set with expires set to a Date 10 years in the future] - expected: FAIL - - [CookieListItem - cookieStore.set with domain set to the current hostname] - expected: FAIL - - [CookieListItem - cookieStore.set with path set to the current directory] - expected: FAIL - - [CookieListItem - cookieStore.set adds / to path if it does not end with /] - expected: FAIL - - [CookieListItem - cookieStore.set with sameSite set to strict] - expected: FAIL - - [CookieListItem - cookieStore.set with sameSite set to lax] - expected: FAIL - - [CookieListItem - cookieStore.set with sameSite set to none] - expected: FAIL - - [CookieListItem - secure defaults to true] - expected: FAIL - - -[cookieListItem_attributes.https.any.html] - [CookieListItem - cookieStore.set defaults with positional name and value] - expected: FAIL - - [CookieListItem - cookieStore.set defaults with name and value in options] - expected: FAIL - - [CookieListItem - cookieStore.set with expires set to a timestamp 10 years in the future] - expected: FAIL - - [CookieListItem - cookieStore.set with expires set to a Date 10 years in the future] - expected: FAIL - - [CookieListItem - cookieStore.set with domain set to the current hostname] - expected: FAIL - - [CookieListItem - cookieStore.set with path set to the current directory] - expected: FAIL - - [CookieListItem - cookieStore.set adds / to path if it does not end with /] - expected: FAIL - - [CookieListItem - cookieStore.set with sameSite set to strict] - expected: FAIL - - [CookieListItem - cookieStore.set with sameSite set to lax] - expected: FAIL - - [CookieListItem - cookieStore.set with sameSite set to none] - expected: FAIL - - [CookieListItem - secure defaults to true] - expected: FAIL diff --git a/testing/web-platform/meta/cookie-store/cookieStore_set_arguments.https.any.js.ini b/testing/web-platform/meta/cookie-store/cookieStore_set_arguments.https.any.js.ini deleted file mode 100644 index 7b02328e89ec..000000000000 --- a/testing/web-platform/meta/cookie-store/cookieStore_set_arguments.https.any.js.ini +++ /dev/null @@ -1,8 +0,0 @@ -[cookieStore_set_arguments.https.any.html] - [cookieStore.set adds / to path that does not end with /] - expected: FAIL - - -[cookieStore_set_arguments.https.any.serviceworker.html] - [cookieStore.set adds / to path that does not end with /] - expected: FAIL