diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index 0f159ad09a2a..d7ed73aee3af 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -516,7 +516,7 @@ Permissions* Navigator::GetPermissions(ErrorResult& aRv) { } if (!mPermissions) { - mPermissions = new Permissions(mWindow->AsGlobal()); + mPermissions = new Permissions(mWindow); } return mPermissions; diff --git a/dom/permission/MidiPermissionStatus.cpp b/dom/permission/MidiPermissionStatus.cpp index 779417a660ae..dd92c413644a 100644 --- a/dom/permission/MidiPermissionStatus.cpp +++ b/dom/permission/MidiPermissionStatus.cpp @@ -11,9 +11,9 @@ namespace mozilla::dom { -MidiPermissionStatus::MidiPermissionStatus(nsIGlobalObject* aGlobal, +MidiPermissionStatus::MidiPermissionStatus(nsPIDOMWindowInner* aWindow, bool aSysex) - : PermissionStatus(aGlobal, PermissionName::Midi), mSysex(aSysex) {} + : PermissionStatus(aWindow, PermissionName::Midi), mSysex(aSysex) {} nsLiteralCString MidiPermissionStatus::GetPermissionType() const { return mSysex ? "midi-sysex"_ns : "midi"_ns; diff --git a/dom/permission/MidiPermissionStatus.h b/dom/permission/MidiPermissionStatus.h index 46e5ef030072..1171754658aa 100644 --- a/dom/permission/MidiPermissionStatus.h +++ b/dom/permission/MidiPermissionStatus.h @@ -13,7 +13,7 @@ namespace mozilla::dom { class MidiPermissionStatus final : public PermissionStatus { public: - MidiPermissionStatus(nsIGlobalObject* aGlobal, bool aSysex); + MidiPermissionStatus(nsPIDOMWindowInner* aWindow, bool aSysex); private: ~MidiPermissionStatus() {} diff --git a/dom/permission/PermissionObserver.cpp b/dom/permission/PermissionObserver.cpp index 9babc4a490f2..26ffd02abc13 100644 --- a/dom/permission/PermissionObserver.cpp +++ b/dom/permission/PermissionObserver.cpp @@ -6,11 +6,12 @@ #include "PermissionObserver.h" +#include "mozilla/dom/PermissionStatus.h" #include "mozilla/dom/WindowGlobalChild.h" #include "mozilla/Services.h" +#include "mozilla/UniquePtr.h" #include "nsIObserverService.h" #include "nsIPermission.h" -#include "PermissionStatusSink.h" #include "PermissionUtils.h" namespace mozilla::dom { @@ -21,13 +22,9 @@ PermissionObserver* gInstance = nullptr; NS_IMPL_ISUPPORTS(PermissionObserver, nsIObserver, nsISupportsWeakReference) -PermissionObserver::PermissionObserver() { - MOZ_ASSERT_DEBUG_OR_FUZZING(NS_IsMainThread()); - MOZ_ASSERT(!gInstance); -} +PermissionObserver::PermissionObserver() { MOZ_ASSERT(!gInstance); } PermissionObserver::~PermissionObserver() { - MOZ_ASSERT_DEBUG_OR_FUZZING(NS_IsMainThread()); MOZ_ASSERT(mSinks.IsEmpty()); MOZ_ASSERT(gInstance == this); @@ -36,8 +33,6 @@ PermissionObserver::~PermissionObserver() { /* static */ already_AddRefed PermissionObserver::GetInstance() { - MOZ_ASSERT_DEBUG_OR_FUZZING(NS_IsMainThread()); - RefPtr instance = gInstance; if (!instance) { instance = new PermissionObserver(); @@ -63,16 +58,14 @@ already_AddRefed PermissionObserver::GetInstance() { return instance.forget(); } -void PermissionObserver::AddSink(PermissionStatusSink* aSink) { - MOZ_ASSERT_DEBUG_OR_FUZZING(NS_IsMainThread()); +void PermissionObserver::AddSink(PermissionStatus* aSink) { MOZ_ASSERT(aSink); MOZ_ASSERT(!mSinks.Contains(aSink)); mSinks.AppendElement(aSink); } -void PermissionObserver::RemoveSink(PermissionStatusSink* aSink) { - MOZ_ASSERT_DEBUG_OR_FUZZING(NS_IsMainThread()); +void PermissionObserver::RemoveSink(PermissionStatus* aSink) { MOZ_ASSERT(aSink); MOZ_ASSERT(mSinks.Contains(aSink)); @@ -82,7 +75,6 @@ void PermissionObserver::RemoveSink(PermissionStatusSink* aSink) { NS_IMETHODIMP PermissionObserver::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData) { - MOZ_ASSERT_DEBUG_OR_FUZZING(NS_IsMainThread()); MOZ_ASSERT(!strcmp(aTopic, "perm-changed") || !strcmp(aTopic, "perm-changed-notify-only")); @@ -110,15 +102,15 @@ PermissionObserver::Observe(nsISupports* aSubject, const char* aTopic, Maybe permission = TypeToPermissionName(type); if (permission) { - for (PermissionStatusSink* sink : mSinks) { - if (sink->Name() != permission.value()) { + for (auto* sink : mSinks) { + if (sink->mName != permission.value()) { continue; } // Check for permissions that are changed for this sink's principal // via the "perm-changed" notification. These permissions affect // the window the sink (PermissionStatus) is held in directly. - if (perm && sink->MaybeUpdatedByOnMainThread(perm)) { - sink->PermissionChangedOnMainThread(); + if (perm && sink->MaybeUpdatedBy(perm)) { + sink->PermissionChanged(); } // Check for permissions that are changed for this sink's principal // via the "perm-changed-notify-only" notification. These permissions @@ -127,9 +119,8 @@ PermissionObserver::Observe(nsISupports* aSubject, const char* aTopic, // example, a "3rdPartyFrameStorage^https://example.com" permission would // return true on these checks where sink is in a window that is same-site // with https://example.com. - if (innerWindow && - sink->MaybeUpdatedByNotifyOnlyOnMainThread(innerWindow)) { - sink->PermissionChangedOnMainThread(); + if (innerWindow && sink->MaybeUpdatedByNotifyOnly(innerWindow)) { + sink->PermissionChanged(); } } } diff --git a/dom/permission/PermissionObserver.h b/dom/permission/PermissionObserver.h index 79f40c4e28ba..f48f26e76a27 100644 --- a/dom/permission/PermissionObserver.h +++ b/dom/permission/PermissionObserver.h @@ -7,13 +7,16 @@ #ifndef mozilla_dom_PermissionObserver_h_ #define mozilla_dom_PermissionObserver_h_ +#include "mozilla/dom/PermissionsBinding.h" + #include "nsIObserver.h" +#include "nsIPrincipal.h" #include "nsTArray.h" #include "nsWeakReference.h" namespace mozilla::dom { -class PermissionStatusSink; +class PermissionStatus; // Singleton that watches for perm-changed notifications in order to notify // PermissionStatus objects. @@ -25,14 +28,14 @@ class PermissionObserver final : public nsIObserver, static already_AddRefed GetInstance(); - void AddSink(PermissionStatusSink* aSink); - void RemoveSink(PermissionStatusSink* aSink); + void AddSink(PermissionStatus* aObs); + void RemoveSink(PermissionStatus* aObs); private: PermissionObserver(); virtual ~PermissionObserver(); - nsTArray> mSinks; + nsTArray mSinks; }; } // namespace mozilla::dom diff --git a/dom/permission/PermissionStatus.cpp b/dom/permission/PermissionStatus.cpp index f1ad58804bc8..586435112edc 100644 --- a/dom/permission/PermissionStatus.cpp +++ b/dom/permission/PermissionStatus.cpp @@ -5,20 +5,21 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/dom/PermissionStatus.h" +#include "mozilla/PermissionDelegateHandler.h" #include "mozilla/AsyncEventDispatcher.h" #include "mozilla/Permission.h" #include "mozilla/Services.h" #include "nsIPermissionManager.h" +#include "PermissionObserver.h" #include "PermissionUtils.h" -#include "PermissionStatusSink.h" #include "nsGlobalWindowInner.h" namespace mozilla::dom { -PermissionStatus::PermissionStatus(nsIGlobalObject* aGlobal, +PermissionStatus::PermissionStatus(nsPIDOMWindowInner* aWindow, PermissionName aName) - : DOMEventTargetHelper(aGlobal), + : DOMEventTargetHelper(aWindow), mName(aName), mState(PermissionState::Denied) { KeepAliveIfHasListenersFor(nsGkAtoms::onchange); @@ -27,26 +28,24 @@ PermissionStatus::PermissionStatus(nsIGlobalObject* aGlobal, // https://w3c.github.io/permissions/#onchange-attribute and // https://w3c.github.io/permissions/#query-method RefPtr PermissionStatus::Init() { - mSink = CreateSink(); - MOZ_ASSERT(mSink); + // Covers the onchange part + // Whenever the user agent is aware that the state of a PermissionStatus + // instance status has changed: ... + // (The observer calls PermissionChanged() to do the steps) + mObserver = PermissionObserver::GetInstance(); + if (NS_WARN_IF(!mObserver)) { + return SimplePromise::CreateAndReject(NS_ERROR_FAILURE, __func__); + } - return mSink->Init()->Then( - GetCurrentSerialEventTarget(), __func__, - [self = RefPtr(this)](const PermissionStatusSink::PermissionStatePromise:: - ResolveOrRejectValue& aResult) { - if (aResult.IsResolve()) { - self->mState = self->ComputeStateFromAction(aResult.ResolveValue()); - return SimplePromise::CreateAndResolve(NS_OK, __func__); - } + mObserver->AddSink(this); - return SimplePromise::CreateAndReject(aResult.RejectValue(), __func__); - }); + // Covers the query part (Step 8.2 - 8.4) + return UpdateState(); } PermissionStatus::~PermissionStatus() { - if (mSink) { - mSink->Disentangle(); - mSink = nullptr; + if (mObserver) { + mObserver->RemoveSink(this); } } @@ -59,28 +58,111 @@ nsLiteralCString PermissionStatus::GetPermissionType() const { return PermissionNameToType(mName); } -// https://w3c.github.io/permissions/#dfn-permissionstatus-update-steps -void PermissionStatus::PermissionChanged(uint32_t aAction) { - PermissionState newState = ComputeStateFromAction(aAction); - if (mState == newState) { - return; +// Covers the calling part of "permission query algorithm" of query() method and +// update steps, which calls +// https://w3c.github.io/permissions/#dfn-default-permission-query-algorithm +// and then https://w3c.github.io/permissions/#dfn-permission-state +RefPtr PermissionStatus::UpdateState() { + // Step 1: If settings wasn't passed, set it to the current settings object. + // Step 2: If settings is a non-secure context, return "denied". + // XXX(krosylight): No such steps here, and no WPT coverage? + + // The permission handler covers the rest of the steps, although the model + // does not exactly match what the spec has. (Not passing "permission key" for + // example) + + RefPtr window = GetOwnerWindow(); + if (NS_WARN_IF(!window)) { + return SimplePromise::CreateAndReject(NS_ERROR_FAILURE, __func__); } - mState = newState; + RefPtr document = window->GetExtantDoc(); + if (NS_WARN_IF(!document)) { + return SimplePromise::CreateAndReject(NS_ERROR_FAILURE, __func__); + } - // Step 4: Queue a task on the permissions task source to fire an - // event named change at status. - RefPtr eventDispatcher = - new AsyncEventDispatcher(this, u"change"_ns, CanBubble::eNo); - eventDispatcher->PostDOMEvent(); + uint32_t action = nsIPermissionManager::DENY_ACTION; + + PermissionDelegateHandler* permissionHandler = + document->GetPermissionDelegateHandler(); + if (NS_WARN_IF(!permissionHandler)) { + return SimplePromise::CreateAndReject(NS_ERROR_FAILURE, __func__); + } + + nsresult rv = permissionHandler->GetPermissionForPermissionsAPI( + GetPermissionType(), &action); + if (NS_WARN_IF(NS_FAILED(rv))) { + return SimplePromise::CreateAndReject(rv, __func__); + } + + mState = ActionToPermissionState(action, mName, *document); + return SimplePromise::CreateAndResolve(NS_OK, __func__); +} + +bool PermissionStatus::MaybeUpdatedBy(nsIPermission* aPermission) const { + NS_ENSURE_TRUE(aPermission, false); + RefPtr window = GetOwnerWindow(); + if (NS_WARN_IF(!window)) { + return false; + } + + Document* doc = window->GetExtantDoc(); + if (NS_WARN_IF(!doc)) { + return false; + } + + nsCOMPtr principal = + Permission::ClonePrincipalForPermission(doc->NodePrincipal()); + NS_ENSURE_TRUE(principal, false); + nsCOMPtr permissionPrincipal; + aPermission->GetPrincipal(getter_AddRefs(permissionPrincipal)); + if (!permissionPrincipal) { + return false; + } + return permissionPrincipal->Equals(principal); +} + +bool PermissionStatus::MaybeUpdatedByNotifyOnly( + nsPIDOMWindowInner* aInnerWindow) const { + return false; +} + +// https://w3c.github.io/permissions/#dfn-permissionstatus-update-steps +void PermissionStatus::PermissionChanged() { + auto oldState = mState; + RefPtr self(this); + // Step 1: If this's relevant global object is a Window object, then: + // Step 1.1: Let document be status's relevant global object's associated + // Document. + // Step 1.2: If document is null or document is not fully active, + // terminate this algorithm. + // TODO(krosylight): WPT /permissions/non-fully-active.https.html fails + // because we don't do this. See bug 1876470. + + // Step 2 - 3 is covered by UpdateState() + UpdateState()->Then( + GetMainThreadSerialEventTarget(), __func__, + [self, oldState]() { + if (self->mState != oldState) { + // Step 4: Queue a task on the permissions task source to fire an + // event named change at status. + RefPtr eventDispatcher = + new AsyncEventDispatcher(self.get(), u"change"_ns, + CanBubble::eNo); + eventDispatcher->PostDOMEvent(); + } + }, + []() { + + }); } void PermissionStatus::DisconnectFromOwner() { IgnoreKeepAliveIfHasListenersFor(nsGkAtoms::onchange); - if (mSink) { - mSink->Disentangle(); - mSink = nullptr; + if (mObserver) { + mObserver->RemoveSink(this); + mObserver = nullptr; } DOMEventTargetHelper::DisconnectFromOwner(); @@ -90,19 +172,4 @@ void PermissionStatus::GetType(nsACString& aName) const { aName.Assign(GetPermissionType()); } -already_AddRefed PermissionStatus::CreateSink() { - RefPtr sink = - new PermissionStatusSink(this, mName, GetPermissionType()); - return sink.forget(); -} - -PermissionState PermissionStatus::ComputeStateFromAction(uint32_t aAction) { - nsCOMPtr global = GetOwnerGlobal(); - if (NS_WARN_IF(!global)) { - return PermissionState::Denied; - } - - return ActionToPermissionState(aAction, mName, global); -} - } // namespace mozilla::dom diff --git a/dom/permission/PermissionStatus.h b/dom/permission/PermissionStatus.h index df289f01d7d8..0b334996d3b0 100644 --- a/dom/permission/PermissionStatus.h +++ b/dom/permission/PermissionStatus.h @@ -11,18 +11,19 @@ #include "mozilla/dom/PermissionStatusBinding.h" #include "mozilla/DOMEventTargetHelper.h" #include "mozilla/MozPromise.h" +#include "nsIPermission.h" namespace mozilla::dom { -class PermissionStatusSink; +class PermissionObserver; class PermissionStatus : public DOMEventTargetHelper { - friend class PermissionStatusSink; + friend class PermissionObserver; public: using SimplePromise = MozPromise; - PermissionStatus(nsIGlobalObject* aGlobal, PermissionName aName); + PermissionStatus(nsPIDOMWindowInner* aWindow, PermissionName aName); JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; @@ -56,14 +57,23 @@ class PermissionStatus : public DOMEventTargetHelper { virtual nsLiteralCString GetPermissionType() const; private: - virtual already_AddRefed CreateSink(); + virtual RefPtr UpdateState(); - void PermissionChanged(uint32_t aAction); + // These functions should be called when an permission is updated which may + // change the state of this PermissionStatus. MaybeUpdatedBy accepts the + // permission object itself that is update. When the permission's key is not + // same-origin with this object's owner window, such as for secondary-keyed + // permissions like `3rdPartyFrameStorage^...`, MaybeUpdatedByNotifyOnly will + // be called with the updated window as an argument. MaybeUpdatedByNotifyOnly + // must be defined by PermissionStatus inheritors that are double-keyed. + virtual bool MaybeUpdatedBy(nsIPermission* aPermission) const; + virtual bool MaybeUpdatedByNotifyOnly(nsPIDOMWindowInner* aInnerWindow) const; - PermissionState ComputeStateFromAction(uint32_t aAction); + void PermissionChanged(); PermissionName mName; - RefPtr mSink; + + RefPtr mObserver; protected: PermissionState mState; diff --git a/dom/permission/PermissionStatusSink.cpp b/dom/permission/PermissionStatusSink.cpp deleted file mode 100644 index 81824b65c049..000000000000 --- a/dom/permission/PermissionStatusSink.cpp +++ /dev/null @@ -1,231 +0,0 @@ -/* -*- 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 "PermissionStatusSink.h" -#include "PermissionObserver.h" -#include "PermissionStatus.h" - -#include "mozilla/Permission.h" -#include "mozilla/PermissionDelegateHandler.h" -#include "mozilla/PermissionManager.h" -#include "mozilla/dom/WorkerPrivate.h" -#include "mozilla/dom/WorkerRef.h" - -namespace mozilla::dom { - -PermissionStatusSink::PermissionStatusSink(PermissionStatus* aPermissionStatus, - PermissionName aPermissionName, - const nsACString& aPermissionType) - : mSerialEventTarget(NS_GetCurrentThread()), - mPermissionStatus(aPermissionStatus), - mMutex("PermissionStatusSink::mMutex"), - mPermissionName(aPermissionName), - mPermissionType(aPermissionType) { - MOZ_ASSERT(aPermissionStatus); - MOZ_ASSERT(mSerialEventTarget); - - nsCOMPtr global = aPermissionStatus->GetOwnerGlobal(); - if (NS_WARN_IF(!global)) { - return; - } - - nsCOMPtr principal = global->PrincipalOrNull(); - if (NS_WARN_IF(!principal)) { - return; - } - - mPrincipalForPermission = Permission::ClonePrincipalForPermission(principal); -} - -PermissionStatusSink::~PermissionStatusSink() = default; - -RefPtr -PermissionStatusSink::Init() { - if (!NS_IsMainThread()) { - WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); - MOZ_ASSERT(workerPrivate); - - MutexAutoLock lock(mMutex); - - mWorkerRef = WeakWorkerRef::Create( - workerPrivate, [self = RefPtr(this)] { self->Disentangle(); }); - } - - return InvokeAsync(GetMainThreadSerialEventTarget(), __func__, - [self = RefPtr(this)] { - MOZ_ASSERT(!self->mObserver); - - // Covers the onchange part - // Whenever the user agent is aware that the state of a - // PermissionStatus instance status has changed: ... (The - // observer calls PermissionChanged() to do the steps) - self->mObserver = PermissionObserver::GetInstance(); - if (NS_WARN_IF(!self->mObserver)) { - return PermissionStatePromise::CreateAndReject( - NS_ERROR_FAILURE, __func__); - } - - self->mObserver->AddSink(self); - - // Covers the query part (Step 8.2 - 8.4) - return self->ComputeStateOnMainThread(); - }); -} - -bool PermissionStatusSink::MaybeUpdatedByOnMainThread( - nsIPermission* aPermission) { - MOZ_ASSERT(NS_IsMainThread()); - - if (!mPrincipalForPermission) { - return false; - } - - nsCOMPtr permissionPrincipal; - aPermission->GetPrincipal(getter_AddRefs(permissionPrincipal)); - if (!permissionPrincipal) { - return false; - } - - return mPrincipalForPermission->Equals(permissionPrincipal); -} - -bool PermissionStatusSink::MaybeUpdatedByNotifyOnlyOnMainThread( - nsPIDOMWindowInner* aInnerWindow) { - MOZ_ASSERT(NS_IsMainThread()); - return false; -} - -void PermissionStatusSink::PermissionChangedOnMainThread() { - MOZ_ASSERT(NS_IsMainThread()); - - ComputeStateOnMainThread()->Then( - mSerialEventTarget, __func__, - [self = RefPtr(this)]( - const PermissionStatePromise::ResolveOrRejectValue& aResult) { - if (aResult.IsResolve() && self->mPermissionStatus) { - self->mPermissionStatus->PermissionChanged(aResult.ResolveValue()); - } - }); -} - -void PermissionStatusSink::Disentangle() { - MOZ_ASSERT(mSerialEventTarget->IsOnCurrentThread()); - - mPermissionStatus = nullptr; - - { - MutexAutoLock lock(mMutex); - mWorkerRef = nullptr; - } - - NS_DispatchToMainThread( - NS_NewRunnableFunction(__func__, [self = RefPtr(this)] { - if (self->mObserver) { - self->mObserver->RemoveSink(self); - self->mObserver = nullptr; - } - })); -} - -RefPtr -PermissionStatusSink::ComputeStateOnMainThread() { - MOZ_ASSERT(NS_IsMainThread()); - - // Step 1: If settings wasn't passed, set it to the current settings object. - // Step 2: If settings is a non-secure context, return "denied". - // XXX(krosylight): No such steps here, and no WPT coverage? - - // The permission handler covers the rest of the steps, although the model - // does not exactly match what the spec has. (Not passing "permission key" for - // example) - - if (mSerialEventTarget->IsOnCurrentThread()) { - if (!mPermissionStatus) { - return PermissionStatePromise::CreateAndReject(NS_ERROR_FAILURE, - __func__); - } - - RefPtr window = mPermissionStatus->GetOwnerWindow(); - return ComputeStateOnMainThreadInternal(window); - } - - nsCOMPtr ancestorWindow; - nsCOMPtr workerPrincipal; - - { - MutexAutoLock lock(mMutex); - - if (!mWorkerRef) { - // We have been disentangled. - return PermissionStatePromise::CreateAndReject(NS_ERROR_FAILURE, - __func__); - } - - // If we have mWorkerRef, we haven't received the WorkerRef notification - // yet. - WorkerPrivate* workerPrivate = mWorkerRef->GetUnsafePrivate(); - MOZ_ASSERT(workerPrivate); - - ancestorWindow = workerPrivate->GetAncestorWindow(); - workerPrincipal = workerPrivate->GetPrincipal(); - } - - if (ancestorWindow) { - return ComputeStateOnMainThreadInternal(ancestorWindow); - } - - if (NS_WARN_IF(!workerPrincipal)) { - return PermissionStatePromise::CreateAndReject(NS_ERROR_FAILURE, __func__); - } - - RefPtr permissionManager = - PermissionManager::GetInstance(); - if (!permissionManager) { - return PermissionStatePromise::CreateAndReject(NS_ERROR_FAILURE, __func__); - } - - uint32_t action = nsIPermissionManager::DENY_ACTION; - nsresult rv = permissionManager->TestPermissionFromPrincipal( - workerPrincipal, mPermissionType, &action); - if (NS_WARN_IF(NS_FAILED(rv))) { - return PermissionStatePromise::CreateAndReject(rv, __func__); - } - - return PermissionStatePromise::CreateAndResolve(action, __func__); -} - -RefPtr -PermissionStatusSink::ComputeStateOnMainThreadInternal( - nsPIDOMWindowInner* aWindow) { - MOZ_ASSERT(NS_IsMainThread()); - - if (NS_WARN_IF(!aWindow)) { - return PermissionStatePromise::CreateAndReject(NS_ERROR_FAILURE, __func__); - } - - RefPtr document = aWindow->GetExtantDoc(); - if (NS_WARN_IF(!document)) { - return PermissionStatePromise::CreateAndReject(NS_ERROR_FAILURE, __func__); - } - - uint32_t action = nsIPermissionManager::DENY_ACTION; - - PermissionDelegateHandler* permissionHandler = - document->GetPermissionDelegateHandler(); - if (NS_WARN_IF(!permissionHandler)) { - return PermissionStatePromise::CreateAndReject(NS_ERROR_FAILURE, __func__); - } - - nsresult rv = permissionHandler->GetPermissionForPermissionsAPI( - mPermissionType, &action); - if (NS_WARN_IF(NS_FAILED(rv))) { - return PermissionStatePromise::CreateAndReject(rv, __func__); - } - - return PermissionStatePromise::CreateAndResolve(action, __func__); -} - -} // namespace mozilla::dom diff --git a/dom/permission/PermissionStatusSink.h b/dom/permission/PermissionStatusSink.h deleted file mode 100644 index 9a13bc6bb3c0..000000000000 --- a/dom/permission/PermissionStatusSink.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- 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_PermissionStatusSink_h -#define mozilla_dom_PermissionStatusSink_h - -#include "mozilla/dom/PermissionsBinding.h" -#include "mozilla/dom/PermissionStatusBinding.h" -#include "mozilla/MozPromise.h" -#include "mozilla/Mutex.h" -#include "nsIPermission.h" - -class nsPIDOMWindowInner; - -namespace mozilla::dom { - -class PermissionObserver; -class PermissionStatus; -class WeakWorkerRef; - -class PermissionStatusSink { - public: - using PermissionStatePromise = MozPromise; - - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PermissionStatusSink) - - PermissionStatusSink(PermissionStatus* aPermissionStatus, - PermissionName aPermissionName, - const nsACString& aPermissionType); - - RefPtr Init(); - - // These functions should be called when an permission is updated which may - // change the state of this PermissionStatus. MaybeUpdatedByOnMainThread - // accepts the permission object itself that is update. When the permission's - // key is not same-origin with this object's owner window/worker, such as for - // secondary-keyed permissions like `3rdPartyFrameStorage^...`, - // MaybeUpdatedByNotifyOnlyOnMainThread will be called with the updated - // window/worker as an argument. MaybeUpdatedByNotifyOnly must be defined by - // PermissionStatus inheritors that are double-keyed. - virtual bool MaybeUpdatedByOnMainThread(nsIPermission* aPermission); - virtual bool MaybeUpdatedByNotifyOnlyOnMainThread( - nsPIDOMWindowInner* aInnerWindow); - - void PermissionChangedOnMainThread(); - - PermissionName Name() const { return mPermissionName; } - - void Disentangle(); - - protected: - virtual ~PermissionStatusSink(); - - virtual RefPtr ComputeStateOnMainThread(); - - RefPtr ComputeStateOnMainThreadInternal( - nsPIDOMWindowInner* aWindow); - - nsCOMPtr mSerialEventTarget; - nsCOMPtr mPrincipalForPermission; - - RefPtr mObserver; - - RefPtr mPermissionStatus; - - Mutex mMutex; - - // Protected by mutex. - // Created and released on worker-thread. Used also on main-thread. - RefPtr mWorkerRef MOZ_GUARDED_BY(mMutex); - - PermissionName mPermissionName; - nsCString mPermissionType; -}; - -} // namespace mozilla::dom - -#endif // mozilla_dom_permissionstatusSink_h diff --git a/dom/permission/PermissionUtils.cpp b/dom/permission/PermissionUtils.cpp index b59bd9c45f57..01bd8ba62092 100644 --- a/dom/permission/PermissionUtils.cpp +++ b/dom/permission/PermissionUtils.cpp @@ -60,9 +60,7 @@ Maybe TypeToPermissionName(const nsACString& aType) { } PermissionState ActionToPermissionState(uint32_t aAction, PermissionName aName, - nsIGlobalObject* aGlobal) { - MOZ_ASSERT(aGlobal); - + const Document& aDocument) { switch (aAction) { case nsIPermissionManager::ALLOW_ACTION: return PermissionState::Granted; @@ -73,7 +71,7 @@ PermissionState ActionToPermissionState(uint32_t aAction, PermissionName aName, case nsIPermissionManager::PROMPT_ACTION: if ((aName == PermissionName::Camera || aName == PermissionName::Microphone) && - !aGlobal->ShouldResistFingerprinting(RFPTarget::MediaDevices)) { + !aDocument.ShouldResistFingerprinting(RFPTarget::MediaDevices)) { // A persisted PROMPT_ACTION means the user chose "Always Ask" // which shows as "granted" to prevent websites from priming the // user to escalate permission any further. diff --git a/dom/permission/PermissionUtils.h b/dom/permission/PermissionUtils.h index 00d378faa0be..2c06173f44c8 100644 --- a/dom/permission/PermissionUtils.h +++ b/dom/permission/PermissionUtils.h @@ -9,7 +9,6 @@ #include "mozilla/dom/PermissionsBinding.h" #include "mozilla/dom/PermissionStatusBinding.h" -#include "mozilla/dom/WorkerPrivate.h" #include "mozilla/Maybe.h" namespace mozilla::dom { @@ -28,7 +27,7 @@ const nsLiteralCString& PermissionNameToType(PermissionName aName); Maybe TypeToPermissionName(const nsACString& aType); PermissionState ActionToPermissionState(uint32_t aAction, PermissionName aName, - nsIGlobalObject* aGlobal); + const Document& aDocument); } // namespace mozilla::dom diff --git a/dom/permission/Permissions.cpp b/dom/permission/Permissions.cpp index c51e1bb0f29a..d9751abf1b4f 100644 --- a/dom/permission/Permissions.cpp +++ b/dom/permission/Permissions.cpp @@ -27,10 +27,9 @@ NS_INTERFACE_MAP_END NS_IMPL_CYCLE_COLLECTING_ADDREF(Permissions) NS_IMPL_CYCLE_COLLECTING_RELEASE(Permissions) -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(Permissions) +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Permissions, mWindow) -Permissions::Permissions(nsIGlobalObject* aGlobal) - : GlobalTeardownObserver(aGlobal) {} +Permissions::Permissions(nsPIDOMWindowInner* aWindow) : mWindow(aWindow) {} Permissions::~Permissions() = default; @@ -46,7 +45,7 @@ namespace { // commands RefPtr CreatePermissionStatus( JSContext* aCx, JS::Handle aPermissionDesc, - nsIGlobalObject* aGlobal, ErrorResult& aRv) { + nsPIDOMWindowInner* aWindow, ErrorResult& aRv) { // Step 2: Let rootDesc be the object permissionDesc refers to, converted to // an IDL value of type PermissionDescriptor. PermissionDescriptor rootDesc; @@ -77,16 +76,16 @@ RefPtr CreatePermissionStatus( return nullptr; } - return new MidiPermissionStatus(aGlobal, midiPerm.mSysex); + return new MidiPermissionStatus(aWindow, midiPerm.mSysex); } case PermissionName::Storage_access: - return new StorageAccessPermissionStatus(aGlobal); + return new StorageAccessPermissionStatus(aWindow); case PermissionName::Geolocation: case PermissionName::Notifications: case PermissionName::Push: case PermissionName::Persistent_storage: case PermissionName::Screen_wake_lock: - return new PermissionStatus(aGlobal, rootDesc.mName); + return new PermissionStatus(aWindow, rootDesc.mName); case PermissionName::Camera: if (!StaticPrefs::permissions_media_query_enabled()) { aRv.ThrowTypeError( @@ -94,7 +93,7 @@ RefPtr CreatePermissionStatus( "a valid value for enumeration PermissionName."); return nullptr; } - return new PermissionStatus(aGlobal, rootDesc.mName); + return new PermissionStatus(aWindow, rootDesc.mName); case PermissionName::Microphone: if (!StaticPrefs::permissions_media_query_enabled()) { aRv.ThrowTypeError( @@ -102,7 +101,7 @@ RefPtr CreatePermissionStatus( "not a valid value for enumeration PermissionName."); return nullptr; } - return new PermissionStatus(aGlobal, rootDesc.mName); + return new PermissionStatus(aWindow, rootDesc.mName); default: MOZ_ASSERT_UNREACHABLE("Unhandled type"); aRv.Throw(NS_ERROR_NOT_IMPLEMENTED); @@ -119,30 +118,23 @@ already_AddRefed Permissions::Query(JSContext* aCx, // Step 1: If this's relevant global object is a Window object, then: // Step 1.1: If the current settings object's associated Document is not fully // active, return a promise rejected with an "InvalidStateError" DOMException. - - nsCOMPtr global = GetOwnerGlobal(); - if (NS_WARN_IF(!global)) { - aRv.ThrowInvalidStateError("The context is not fully active."); + // + // TODO(krosylight): The spec allows worker global while we don't, see bug + // 1193373. + if (!mWindow || !mWindow->IsFullyActive()) { + aRv.ThrowInvalidStateError("The document is not fully active."); return nullptr; } - if (NS_IsMainThread()) { - nsCOMPtr window = do_QueryInterface(global); - if (!window || !window->IsFullyActive()) { - aRv.ThrowInvalidStateError("The document is not fully active."); - return nullptr; - } - } - // Step 2 - 6 and 8.1: RefPtr status = - CreatePermissionStatus(aCx, aPermission, global, aRv); + CreatePermissionStatus(aCx, aPermission, mWindow, aRv); if (!status) { return nullptr; } // Step 7: Let promise be a new promise. - RefPtr promise = Promise::Create(global, aRv); + RefPtr promise = Promise::Create(mWindow->AsGlobal(), aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } @@ -151,7 +143,7 @@ already_AddRefed Permissions::Query(JSContext* aCx, // Step 8.4: Queue a global task on the permissions task source with this's // relevant global object to resolve promise with status. status->Init()->Then( - GetCurrentSerialEventTarget(), __func__, + GetMainThreadSerialEventTarget(), __func__, [status, promise]() { promise->MaybeResolve(status); return; diff --git a/dom/permission/Permissions.h b/dom/permission/Permissions.h index 1ca9e45a8775..f6cfd4ae6568 100644 --- a/dom/permission/Permissions.h +++ b/dom/permission/Permissions.h @@ -8,10 +8,8 @@ #define mozilla_dom_Permissions_h_ #include "nsISupports.h" +#include "nsPIDOMWindow.h" #include "nsWrapperCache.h" -#include "mozilla/GlobalTeardownObserver.h" - -class nsIGlobalObject; namespace mozilla { @@ -23,14 +21,14 @@ class Promise; class PermissionStatus; struct PermissionSetParameters; -class Permissions final : public GlobalTeardownObserver, public nsWrapperCache { +class Permissions final : public nsISupports, public nsWrapperCache { public: NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(Permissions) - explicit Permissions(nsIGlobalObject* aGlobal); + explicit Permissions(nsPIDOMWindowInner* aWindow); - nsIGlobalObject* GetParentObject() const { return GetOwnerGlobal(); } + nsPIDOMWindowInner* GetParentObject() const { return mWindow; } JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; @@ -47,6 +45,8 @@ class Permissions final : public GlobalTeardownObserver, public nsWrapperCache { private: ~Permissions(); + + nsCOMPtr mWindow; }; } // namespace dom diff --git a/dom/permission/StorageAccessPermissionStatus.cpp b/dom/permission/StorageAccessPermissionStatus.cpp index a2129747fb6f..7480df765ede 100644 --- a/dom/permission/StorageAccessPermissionStatus.cpp +++ b/dom/permission/StorageAccessPermissionStatus.cpp @@ -12,152 +12,62 @@ #include "mozilla/dom/FeaturePolicyUtils.h" #include "mozilla/dom/PermissionStatus.h" #include "mozilla/dom/PermissionStatusBinding.h" -#include "mozilla/dom/WorkerPrivate.h" -#include "mozilla/dom/WorkerRef.h" #include "nsGlobalWindowInner.h" #include "nsIPermissionManager.h" -#include "PermissionStatusSink.h" namespace mozilla::dom { -class StorageAccessPermissionStatusSink final : public PermissionStatusSink { - Mutex mWorkerRefMutex; - - // Protected by mutex. - // Created and released on worker-thread. Used also on main-thread. - RefPtr mWeakWorkerRef MOZ_GUARDED_BY(mWorkerRefMutex); - - public: - StorageAccessPermissionStatusSink(PermissionStatus* aPermissionStatus, - PermissionName aPermissionName, - const nsACString& aPermissionType) - : PermissionStatusSink(aPermissionStatus, aPermissionName, - aPermissionType), - mWorkerRefMutex("StorageAccessPermissionStatusSink::mWorkerRefMutex") {} - - void Init() { - if (!NS_IsMainThread()) { - WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); - MOZ_ASSERT(workerPrivate); - - MutexAutoLock lock(mWorkerRefMutex); - - mWeakWorkerRef = - WeakWorkerRef::Create(workerPrivate, [self = RefPtr(this)]() { - MutexAutoLock lock(self->mWorkerRefMutex); - self->mWeakWorkerRef = nullptr; - }); - } - } - - protected: - bool MaybeUpdatedByOnMainThread(nsIPermission* aPermission) override { - return false; - } - - bool MaybeUpdatedByNotifyOnlyOnMainThread( - nsPIDOMWindowInner* aInnerWindow) override { - NS_ENSURE_TRUE(aInnerWindow, false); - - if (!mPermissionStatus) { - return false; - } - - nsCOMPtr ownerWindow; - - if (mSerialEventTarget->IsOnCurrentThread()) { - ownerWindow = mPermissionStatus->GetOwnerWindow(); - } else { - MutexAutoLock lock(mWorkerRefMutex); - - if (!mWeakWorkerRef) { - return false; - } - - // If we have mWeakWorkerRef, we haven't received the WorkerRef - // notification yet. - WorkerPrivate* workerPrivate = mWeakWorkerRef->GetUnsafePrivate(); - MOZ_ASSERT(workerPrivate); - - ownerWindow = workerPrivate->GetAncestorWindow(); - } - - NS_ENSURE_TRUE(ownerWindow, false); - - return ownerWindow->WindowID() == aInnerWindow->WindowID(); - } - - RefPtr ComputeStateOnMainThread() override { - if (mSerialEventTarget->IsOnCurrentThread()) { - if (!mPermissionStatus) { - return PermissionStatePromise::CreateAndReject(NS_ERROR_FAILURE, - __func__); - } - - nsGlobalWindowInner* window = mPermissionStatus->GetOwnerWindow(); - if (NS_WARN_IF(!window)) { - return PermissionStatePromise::CreateAndReject(NS_ERROR_FAILURE, - __func__); - } - - WindowGlobalChild* wgc = window->GetWindowGlobalChild(); - if (NS_WARN_IF(!wgc)) { - return PermissionStatePromise::CreateAndReject(NS_ERROR_FAILURE, - __func__); - } - - // Perform a Permission Policy Request - if (!FeaturePolicyUtils::IsFeatureAllowed(window->GetExtantDoc(), - u"storage-access"_ns)) { - return PermissionStatePromise::CreateAndResolve( - nsIPermissionManager::PROMPT_ACTION, __func__); - } - - return wgc->SendGetStorageAccessPermission(false)->Then( - GetMainThreadSerialEventTarget(), __func__, - [self = RefPtr(this)](uint32_t aAction) { - // We never reveal PermissionState::Denied here - return PermissionStatePromise::CreateAndResolve( - aAction == nsIPermissionManager::ALLOW_ACTION - ? aAction - : nsIPermissionManager::PROMPT_ACTION, - __func__); - }, - [](mozilla::ipc::ResponseRejectReason aError) { - return PermissionStatePromise::CreateAndReject(NS_ERROR_FAILURE, - __func__); - }); - } - - // For workers we already have the correct value in workerPrivate. - return InvokeAsync(mSerialEventTarget, __func__, [self = RefPtr(this)] { - if (!self->mPermissionStatus) { - return PermissionStatePromise::CreateAndReject(NS_ERROR_FAILURE, - __func__); - } - - WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); - MOZ_ASSERT(workerPrivate); - - return PermissionStatePromise::CreateAndResolve( - workerPrivate->StorageAccess() == StorageAccess::eAllow - ? nsIPermissionManager::ALLOW_ACTION - : nsIPermissionManager::PROMPT_ACTION, - __func__); - }); - } -}; - StorageAccessPermissionStatus::StorageAccessPermissionStatus( - nsIGlobalObject* aGlobal) - : PermissionStatus(aGlobal, PermissionName::Storage_access) {} + nsPIDOMWindowInner* aWindow) + : PermissionStatus(aWindow, PermissionName::Storage_access) {} -already_AddRefed -StorageAccessPermissionStatus::CreateSink() { - RefPtr sink = - new StorageAccessPermissionStatusSink(this, Name(), GetPermissionType()); - sink->Init(); - return sink.forget(); +RefPtr +StorageAccessPermissionStatus::UpdateState() { + nsGlobalWindowInner* window = GetOwnerWindow(); + if (NS_WARN_IF(!window)) { + return SimplePromise::CreateAndReject(NS_ERROR_FAILURE, __func__); + } + + WindowGlobalChild* wgc = window->GetWindowGlobalChild(); + if (NS_WARN_IF(!wgc)) { + return SimplePromise::CreateAndReject(NS_ERROR_FAILURE, __func__); + } + + // Perform a Permission Policy Request + if (!FeaturePolicyUtils::IsFeatureAllowed(window->GetExtantDoc(), + u"storage-access"_ns)) { + mState = PermissionState::Prompt; + return SimplePromise::CreateAndResolve(NS_OK, __func__); + } + + RefPtr self(this); + return wgc->SendGetStorageAccessPermission(false)->Then( + GetMainThreadSerialEventTarget(), __func__, + [self](uint32_t aAction) { + if (aAction == nsIPermissionManager::ALLOW_ACTION) { + self->mState = PermissionState::Granted; + } else { + // We never reveal PermissionState::Denied here + self->mState = PermissionState::Prompt; + } + return SimplePromise::CreateAndResolve(NS_OK, __func__); + }, + [](mozilla::ipc::ResponseRejectReason aError) { + return SimplePromise::CreateAndResolve(NS_ERROR_FAILURE, __func__); + }); +} + +bool StorageAccessPermissionStatus::MaybeUpdatedBy( + nsIPermission* aPermission) const { + return false; +} + +bool StorageAccessPermissionStatus::MaybeUpdatedByNotifyOnly( + nsPIDOMWindowInner* aInnerWindow) const { + nsPIDOMWindowInner* owner = GetOwnerWindow(); + NS_ENSURE_TRUE(owner, false); + NS_ENSURE_TRUE(aInnerWindow, false); + return owner->WindowID() == aInnerWindow->WindowID(); } } // namespace mozilla::dom diff --git a/dom/permission/StorageAccessPermissionStatus.h b/dom/permission/StorageAccessPermissionStatus.h index 3ca653c40b22..be984b576225 100644 --- a/dom/permission/StorageAccessPermissionStatus.h +++ b/dom/permission/StorageAccessPermissionStatus.h @@ -11,15 +11,16 @@ namespace mozilla::dom { -// The storage access permission from the Storage Access API has unique -// implementation details and should not be used as the basis for any other -// status sink implementations. class StorageAccessPermissionStatus final : public PermissionStatus { public: - explicit StorageAccessPermissionStatus(nsIGlobalObject* aGlobal); + explicit StorageAccessPermissionStatus(nsPIDOMWindowInner* aWindow); private: - already_AddRefed CreateSink() override; + RefPtr UpdateState() override; + + bool MaybeUpdatedBy(nsIPermission* aPermission) const override; + bool MaybeUpdatedByNotifyOnly( + nsPIDOMWindowInner* aInnerWindow) const override; }; } // namespace mozilla::dom diff --git a/dom/permission/moz.build b/dom/permission/moz.build index 764448710c47..be22a2db03d5 100644 --- a/dom/permission/moz.build +++ b/dom/permission/moz.build @@ -20,7 +20,6 @@ UNIFIED_SOURCES += [ "PermissionObserver.cpp", "Permissions.cpp", "PermissionStatus.cpp", - "PermissionStatusSink.cpp", "PermissionUtils.cpp", "StorageAccessPermissionStatus.cpp", ] diff --git a/dom/serviceworkers/test/test_serviceworker_interfaces.js b/dom/serviceworkers/test/test_serviceworker_interfaces.js index 3be9da856fac..50deb1b579f5 100644 --- a/dom/serviceworkers/test/test_serviceworker_interfaces.js +++ b/dom/serviceworkers/test/test_serviceworker_interfaces.js @@ -292,10 +292,6 @@ let interfaceNamesInGlobalScope = [ // IMPORTANT: Do not change this list without review from a DOM peer! "PerformanceServerTiming", // IMPORTANT: Do not change this list without review from a DOM peer! - "Permissions", - // IMPORTANT: Do not change this list without review from a DOM peer! - "PermissionStatus", - // IMPORTANT: Do not change this list without review from a DOM peer! "ProgressEvent", // IMPORTANT: Do not change this list without review from a DOM peer! "PromiseRejectionEvent", diff --git a/dom/webidl/Navigator.webidl b/dom/webidl/Navigator.webidl index 96261229ad08..a015e21d0037 100644 --- a/dom/webidl/Navigator.webidl +++ b/dom/webidl/Navigator.webidl @@ -106,9 +106,8 @@ interface mixin NavigatorStorageUtils { //undefined yieldForStorageUpdates(); }; -// https://w3c.github.io/permissions/#webidl-2112232240 partial interface Navigator { - [Throws, SameObject] + [Throws] readonly attribute Permissions permissions; }; diff --git a/dom/webidl/PermissionStatus.webidl b/dom/webidl/PermissionStatus.webidl index 808eff7a7e1d..fa29f2de53c1 100644 --- a/dom/webidl/PermissionStatus.webidl +++ b/dom/webidl/PermissionStatus.webidl @@ -13,7 +13,7 @@ enum PermissionState { "prompt" }; -[Exposed=(Window,Worker)] +[Exposed=Window] interface PermissionStatus : EventTarget { readonly attribute PermissionName name; readonly attribute PermissionState state; diff --git a/dom/webidl/Permissions.webidl b/dom/webidl/Permissions.webidl index 40b1d671c703..3a5d7f2c9711 100644 --- a/dom/webidl/Permissions.webidl +++ b/dom/webidl/Permissions.webidl @@ -33,7 +33,7 @@ dictionary MidiPermissionDescriptor : PermissionDescriptor { // We don't implement `PushPermissionDescriptor` because we use a background // message quota instead of `userVisibleOnly`. -[Exposed=(Window,Worker)] +[Exposed=Window] interface Permissions { [NewObject] Promise query(object permission); diff --git a/dom/webidl/WorkerNavigator.webidl b/dom/webidl/WorkerNavigator.webidl index 76cc979c1336..34d01935d979 100644 --- a/dom/webidl/WorkerNavigator.webidl +++ b/dom/webidl/WorkerNavigator.webidl @@ -34,10 +34,3 @@ WorkerNavigator includes NavigatorLocks; // https://gpuweb.github.io/gpuweb/#navigator-gpu WorkerNavigator includes NavigatorGPU; - - -// https://w3c.github.io/permissions/#webidl-2112232240 -[Exposed=(Worker)] -partial interface WorkerNavigator { - [SameObject] readonly attribute Permissions permissions; -}; diff --git a/dom/workers/WorkerNavigator.cpp b/dom/workers/WorkerNavigator.cpp index 018c86116277..ed5956cae1f1 100644 --- a/dom/workers/WorkerNavigator.cpp +++ b/dom/workers/WorkerNavigator.cpp @@ -16,7 +16,6 @@ #include "mozilla/dom/LockManager.h" #include "mozilla/dom/MediaCapabilities.h" #include "mozilla/dom/Navigator.h" -#include "mozilla/dom/Permissions.h" #include "mozilla/dom/StorageManager.h" #include "mozilla/dom/WorkerCommon.h" #include "mozilla/dom/WorkerNavigatorBinding.h" @@ -51,7 +50,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(WorkerNavigator) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaCapabilities) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWebGpu) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocks) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPermissions) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END WorkerNavigator::WorkerNavigator(const NavigatorProperties& aProperties, @@ -89,8 +87,6 @@ void WorkerNavigator::Invalidate() { mLocks->Shutdown(); mLocks = nullptr; } - - mPermissions = nullptr; } JSObject* WorkerNavigator::WrapObject(JSContext* aCx, @@ -290,18 +286,4 @@ dom::LockManager* WorkerNavigator::Locks() { return mLocks; } -dom::Permissions* WorkerNavigator::Permissions() { - if (!mPermissions) { - WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); - MOZ_ASSERT(workerPrivate); - - nsIGlobalObject* global = workerPrivate->GlobalScope(); - MOZ_ASSERT(global); - - mPermissions = new dom::Permissions(global); - } - - return mPermissions; -} - } // namespace mozilla::dom diff --git a/dom/workers/WorkerNavigator.h b/dom/workers/WorkerNavigator.h index 6681c9caf34b..0db9292d7881 100644 --- a/dom/workers/WorkerNavigator.h +++ b/dom/workers/WorkerNavigator.h @@ -31,7 +31,6 @@ namespace dom { class StorageManager; class MediaCapabilities; class LockManager; -class Permissions; namespace network { class Connection; @@ -47,7 +46,6 @@ class WorkerNavigator final : public nsWrapperCache { RefPtr mMediaCapabilities; RefPtr mWebGpu; RefPtr mLocks; - RefPtr mPermissions; bool mOnline; WorkerNavigator(const NavigatorProperties& aProperties, bool aOnline); @@ -115,8 +113,6 @@ class WorkerNavigator final : public nsWrapperCache { webgpu::Instance* Gpu(); dom::LockManager* Locks(); - - dom::Permissions* Permissions(); }; } // namespace dom diff --git a/dom/workers/test/navigator_worker.js b/dom/workers/test/navigator_worker.js index be4927beb6e1..a9cd4f29d583 100644 --- a/dom/workers/test/navigator_worker.js +++ b/dom/workers/test/navigator_worker.js @@ -20,7 +20,6 @@ var supportedProps = [ "hardwareConcurrency", { name: "storage", isSecureContext: true }, "connection", - "permissions", ]; self.onmessage = function (event) { diff --git a/dom/workers/test/test_navigator_iframe.js b/dom/workers/test/test_navigator_iframe.js index f1646a79915e..248d7ed2cd60 100644 --- a/dom/workers/test/test_navigator_iframe.js +++ b/dom/workers/test/test_navigator_iframe.js @@ -31,7 +31,6 @@ worker.onmessage = function (event) { "gpu", "locks", "mediaCapabilities", - "permissions", "storage", ]; diff --git a/dom/workers/test/test_worker_interfaces.js b/dom/workers/test/test_worker_interfaces.js index d319261a8fa0..6838176396c2 100644 --- a/dom/workers/test/test_worker_interfaces.js +++ b/dom/workers/test/test_worker_interfaces.js @@ -302,10 +302,6 @@ let interfaceNamesInGlobalScope = [ // IMPORTANT: Do not change this list without review from a DOM peer! { name: "PerformanceServerTiming", insecureContext: false }, // IMPORTANT: Do not change this list without review from a DOM peer! - { name: "Permissions", insecureContext: true }, - // IMPORTANT: Do not change this list without review from a DOM peer! - { name: "PermissionStatus", insecureContext: true }, - // IMPORTANT: Do not change this list without review from a DOM peer! { name: "ProgressEvent", insecureContext: true }, // IMPORTANT: Do not change this list without review from a DOM peer! { name: "PromiseRejectionEvent", insecureContext: true }, diff --git a/testing/web-platform/meta/permissions/idlharness.any.js.ini b/testing/web-platform/meta/permissions/idlharness.any.js.ini new file mode 100644 index 000000000000..3c926415e489 --- /dev/null +++ b/testing/web-platform/meta/permissions/idlharness.any.js.ini @@ -0,0 +1,84 @@ +[idlharness.any.worker.html] + [Permissions interface: existence and properties of interface prototype object's "constructor" property] + expected: FAIL + + [PermissionStatus interface: existence and properties of interface prototype object's "constructor" property] + expected: FAIL + + [Permissions interface: existence and properties of interface prototype object] + expected: FAIL + + [Permissions interface: navigator.permissions must inherit property "query(object)" with the proper type] + expected: FAIL + + [PermissionStatus interface: permissionStatus must inherit property "onchange" with the proper type] + expected: FAIL + + [PermissionStatus interface: existence and properties of interface prototype object] + expected: FAIL + + [Permissions interface object name] + expected: FAIL + + [WorkerNavigator interface: attribute permissions] + expected: FAIL + + [Permissions interface: existence and properties of interface prototype object's @@unscopables property] + expected: FAIL + + [WorkerNavigator interface: navigator must inherit property "permissions" with the proper type] + expected: FAIL + + [Permissions interface object length] + expected: FAIL + + [Permissions interface: operation query(object)] + expected: FAIL + + [PermissionStatus interface object name] + expected: FAIL + + [PermissionStatus interface: attribute state] + expected: FAIL + + [PermissionStatus interface: existence and properties of interface object] + expected: FAIL + + [Permissions must be primary interface of navigator.permissions] + expected: FAIL + + [PermissionStatus interface: existence and properties of interface prototype object's @@unscopables property] + expected: FAIL + + [PermissionStatus interface: attribute onchange] + expected: FAIL + + [PermissionStatus must be primary interface of permissionStatus] + expected: FAIL + + [PermissionStatus interface object length] + expected: FAIL + + [PermissionStatus interface: permissionStatus must inherit property "state" with the proper type] + expected: FAIL + + [Permissions interface: existence and properties of interface object] + expected: FAIL + + [Stringification of permissionStatus] + expected: FAIL + + [Stringification of navigator.permissions] + expected: FAIL + + [Permissions interface: calling query(object) on navigator.permissions with too few arguments must throw TypeError] + expected: FAIL + + [PermissionStatus interface: attribute name] + expected: FAIL + + [PermissionStatus interface: permissionStatus must inherit property "name" with the proper type] + expected: FAIL + + +[idlharness.any.html] diff --git a/testing/web-platform/meta/storage/permission-query.https.any.js.ini b/testing/web-platform/meta/storage/permission-query.https.any.js.ini new file mode 100644 index 000000000000..8bd90e07b952 --- /dev/null +++ b/testing/web-platform/meta/storage/permission-query.https.any.js.ini @@ -0,0 +1,6 @@ +[permission-query.https.any.worker.html] + [The "persistent-storage" permission is recognized] + expected: FAIL + + +[permission-query.https.any.html]