diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /dom/permission/Permissions.cpp | |
parent | Initial commit. (diff) | |
download | firefox-esr-upstream.tar.xz firefox-esr-upstream.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/permission/Permissions.cpp')
-rw-r--r-- | dom/permission/Permissions.cpp | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/dom/permission/Permissions.cpp b/dom/permission/Permissions.cpp new file mode 100644 index 0000000000..571dec7630 --- /dev/null +++ b/dom/permission/Permissions.cpp @@ -0,0 +1,182 @@ +/* -*- 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 "mozilla/dom/Permissions.h" + +#include "mozilla/dom/ContentChild.h" +#include "mozilla/dom/Document.h" +#include "mozilla/dom/MidiPermissionStatus.h" +#include "mozilla/dom/PermissionMessageUtils.h" +#include "mozilla/dom/PermissionStatus.h" +#include "mozilla/dom/PermissionsBinding.h" +#include "mozilla/dom/Promise.h" +#include "mozilla/Components.h" +#include "nsIPermissionManager.h" +#include "PermissionUtils.h" + +namespace mozilla::dom { + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Permissions) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +NS_IMPL_CYCLE_COLLECTING_ADDREF(Permissions) +NS_IMPL_CYCLE_COLLECTING_RELEASE(Permissions) + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Permissions, mWindow) + +Permissions::Permissions(nsPIDOMWindowInner* aWindow) : mWindow(aWindow) {} + +Permissions::~Permissions() = default; + +JSObject* Permissions::WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) { + return Permissions_Binding::Wrap(aCx, this, aGivenProto); +} + +namespace { + +already_AddRefed<PermissionStatus> CreatePermissionStatus( + JSContext* aCx, JS::Handle<JSObject*> aPermission, + nsPIDOMWindowInner* aWindow, ErrorResult& aRv) { + PermissionDescriptor permission; + JS::Rooted<JS::Value> value(aCx, JS::ObjectOrNullValue(aPermission)); + if (NS_WARN_IF(!permission.Init(aCx, value))) { + aRv.NoteJSContextException(aCx); + return nullptr; + } + + switch (permission.mName) { + case PermissionName::Midi: { + MidiPermissionDescriptor midiPerm; + if (NS_WARN_IF(!midiPerm.Init(aCx, value))) { + aRv.NoteJSContextException(aCx); + return nullptr; + } + + bool sysex = midiPerm.mSysex.WasPassed() && midiPerm.mSysex.Value(); + return MidiPermissionStatus::Create(aWindow, sysex, aRv); + } + case PermissionName::Geolocation: + case PermissionName::Notifications: + case PermissionName::Push: + case PermissionName::Persistent_storage: + return PermissionStatus::Create(aWindow, permission.mName, aRv); + + default: + MOZ_ASSERT_UNREACHABLE("Unhandled type"); + aRv.Throw(NS_ERROR_NOT_IMPLEMENTED); + return nullptr; + } +} + +} // namespace + +already_AddRefed<Promise> Permissions::Query(JSContext* aCx, + JS::Handle<JSObject*> aPermission, + ErrorResult& aRv) { + if (!mWindow || !mWindow->IsFullyActive()) { + aRv.ThrowInvalidStateError("The document is not fully active."); + return nullptr; + } + + RefPtr<PermissionStatus> status = + CreatePermissionStatus(aCx, aPermission, mWindow, aRv); + if (NS_WARN_IF(aRv.Failed())) { + MOZ_ASSERT(!status); + return nullptr; + } + + MOZ_ASSERT(status); + RefPtr<Promise> promise = Promise::Create(mWindow->AsGlobal(), aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + promise->MaybeResolve(status); + return promise.forget(); +} + +/* static */ +nsresult Permissions::RemovePermission(nsIPrincipal* aPrincipal, + const nsACString& aPermissionType) { + MOZ_ASSERT(XRE_IsParentProcess()); + + nsCOMPtr<nsIPermissionManager> permMgr = + components::PermissionManager::Service(); + if (NS_WARN_IF(!permMgr)) { + return NS_ERROR_FAILURE; + } + + return permMgr->RemoveFromPrincipal(aPrincipal, aPermissionType); +} + +already_AddRefed<Promise> Permissions::Revoke(JSContext* aCx, + JS::Handle<JSObject*> aPermission, + ErrorResult& aRv) { + if (!mWindow) { + aRv.Throw(NS_ERROR_UNEXPECTED); + return nullptr; + } + + PermissionDescriptor permission; + JS::Rooted<JS::Value> value(aCx, JS::ObjectOrNullValue(aPermission)); + if (NS_WARN_IF(!permission.Init(aCx, value))) { + aRv.NoteJSContextException(aCx); + return nullptr; + } + + RefPtr<Promise> promise = Promise::Create(mWindow->AsGlobal(), aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + nsCOMPtr<Document> document = mWindow->GetExtantDoc(); + if (!document) { + promise->MaybeReject(NS_ERROR_UNEXPECTED); + return promise.forget(); + } + + nsCOMPtr<nsIPermissionManager> permMgr = + components::PermissionManager::Service(); + if (NS_WARN_IF(!permMgr)) { + promise->MaybeReject(NS_ERROR_FAILURE); + return promise.forget(); + } + + const nsLiteralCString& permissionType = + PermissionNameToType(permission.mName); + + nsresult rv; + if (XRE_IsParentProcess()) { + rv = RemovePermission(document->NodePrincipal(), permissionType); + } else { + // Permissions can't be removed from the content process. Send a message + // to the parent; `ContentParent::RecvRemovePermission` will call + // `RemovePermission`. + ContentChild::GetSingleton()->SendRemovePermission( + document->NodePrincipal(), permissionType, &rv); + } + + if (NS_WARN_IF(NS_FAILED(rv))) { + promise->MaybeReject(rv); + return promise.forget(); + } + + RefPtr<PermissionStatus> status = + CreatePermissionStatus(aCx, aPermission, mWindow, aRv); + if (NS_WARN_IF(aRv.Failed())) { + MOZ_ASSERT(!status); + return nullptr; + } + + MOZ_ASSERT(status); + promise->MaybeResolve(status); + return promise.forget(); +} + +} // namespace mozilla::dom |