From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- dom/permission/Permissions.cpp | 176 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 dom/permission/Permissions.cpp (limited to 'dom/permission/Permissions.cpp') diff --git a/dom/permission/Permissions.cpp b/dom/permission/Permissions.cpp new file mode 100644 index 0000000000..a74f65b80c --- /dev/null +++ b/dom/permission/Permissions.cpp @@ -0,0 +1,176 @@ +/* -*- 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/Document.h" +#include "mozilla/dom/MidiPermissionStatus.h" +#include "mozilla/dom/PermissionSetParametersBinding.h" +#include "mozilla/dom/PermissionStatus.h" +#include "mozilla/dom/PermissionsBinding.h" +#include "mozilla/dom/Promise.h" +#include "mozilla/dom/RootedDictionary.h" +#include "mozilla/dom/StorageAccessPermissionStatus.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 aGivenProto) { + return Permissions_Binding::Wrap(aCx, this, aGivenProto); +} + +namespace { + +// Steps to parse PermissionDescriptor in +// https://w3c.github.io/permissions/#query-method and relevant WebDriver +// commands +RefPtr CreatePermissionStatus( + JSContext* aCx, JS::Handle aPermissionDesc, + nsPIDOMWindowInner* aWindow, ErrorResult& aRv) { + // Step 2: Let rootDesc be the object permissionDesc refers to, converted to + // an IDL value of type PermissionDescriptor. + PermissionDescriptor rootDesc; + JS::Rooted permissionDescValue( + aCx, JS::ObjectOrNullValue(aPermissionDesc)); + if (NS_WARN_IF(!rootDesc.Init(aCx, permissionDescValue))) { + // Step 3: If the conversion throws an exception, return a promise rejected + // with that exception. + // Step 4: If rootDesc["name"] is not supported, return a promise rejected + // with a TypeError. (This is done by `enum PermissionName`, as the spec + // note says: "implementers are encouraged to use their own custom enum + // here") + aRv.NoteJSContextException(aCx); + return nullptr; + } + + // Step 5: Let typedDescriptor be the object permissionDesc refers to, + // converted to an IDL value of rootDesc's name's permission descriptor type. + // Step 6: If the conversion throws an exception, return a promise rejected + // with that exception. + // Step 8.1: Let status be create a PermissionStatus with typedDescriptor. + // (The rest is done by the caller) + switch (rootDesc.mName) { + case PermissionName::Midi: { + MidiPermissionDescriptor midiPerm; + if (NS_WARN_IF(!midiPerm.Init(aCx, permissionDescValue))) { + aRv.NoteJSContextException(aCx); + return nullptr; + } + + return new MidiPermissionStatus(aWindow, midiPerm.mSysex); + } + case PermissionName::Storage_access: + 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(aWindow, rootDesc.mName); + default: + MOZ_ASSERT_UNREACHABLE("Unhandled type"); + aRv.Throw(NS_ERROR_NOT_IMPLEMENTED); + return nullptr; + } +} + +} // namespace + +// https://w3c.github.io/permissions/#query-method +already_AddRefed Permissions::Query(JSContext* aCx, + JS::Handle aPermission, + ErrorResult& aRv) { + // 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. + // + // 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; + } + + // Step 2 - 6 and 8.1: + RefPtr status = + CreatePermissionStatus(aCx, aPermission, mWindow, aRv); + if (!status) { + return nullptr; + } + + // Step 7: Let promise be a new promise. + RefPtr promise = Promise::Create(mWindow->AsGlobal(), aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + // Step 8.2 - 8.3: (Done by the Init method) + // 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( + GetMainThreadSerialEventTarget(), __func__, + [status, promise]() { + promise->MaybeResolve(status); + return; + }, + [promise](nsresult aError) { + MOZ_ASSERT(NS_FAILED(aError)); + NS_WARNING("Failed PermissionStatus creation"); + promise->MaybeReject(aError); + return; + }); + + return promise.forget(); +} + +already_AddRefed Permissions::ParseSetParameters( + JSContext* aCx, const PermissionSetParameters& aParameters, + ErrorResult& aRv) { + // Step 1: Let parametersDict be the parameters argument, converted to an IDL + // value of type PermissionSetParameters. If this throws an exception, + // return an invalid argument error. + // (Done by IDL layer, and the error type should be handled by the caller) + + // Step 2: If parametersDict.state is an inappropriate permission state for + // any implementation-defined reason, return a invalid argument error. + // (We don't do this) + + // Step 3: Let rootDesc be parametersDict.descriptor. + JS::Rooted rootDesc(aCx, aParameters.mDescriptor); + + // Step 4: Let typedDescriptor be the object rootDesc refers to, converted + // to an IDL value of rootDesc.name's permission descriptor type. If this + // throws an exception, return a invalid argument error. + // + // We use PermissionStatus as the typed object. + RefPtr status = + CreatePermissionStatus(aCx, rootDesc, nullptr, aRv); + if (aRv.Failed()) { + return nullptr; + } + + // Set the state too so that the caller can use it for step 5. + status->SetState(aParameters.mState); + + return status.forget(); +} + +} // namespace mozilla::dom -- cgit v1.2.3