зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1876754 - Add Permissions::ParseSetParameters for webdriver r=webdriver-reviewers,webidl,smaug,whimboo
Differential Revision: https://phabricator.services.mozilla.com/D200941
This commit is contained in:
Родитель
cbb35c98d7
Коммит
466dba5633
|
@ -0,0 +1,18 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* https://w3c.github.io/permissions/#permissions-interface
|
||||
*
|
||||
* This file is in chrome-webidl as:
|
||||
* 1. This is for webdriver and is not directly exposed to web
|
||||
* 2. Putting this to webidl/Permissions.webidl causes header inclusion conflict
|
||||
*/
|
||||
|
||||
[GenerateInit]
|
||||
dictionary PermissionSetParameters {
|
||||
required object descriptor;
|
||||
required PermissionState state;
|
||||
};
|
|
@ -82,6 +82,7 @@ WEBIDL_FILES = [
|
|||
"MozStorageStatementRow.webidl",
|
||||
"NetDashboard.webidl",
|
||||
"PathUtils.webidl",
|
||||
"PermissionSetParameters.webidl",
|
||||
"PrecompiledScript.webidl",
|
||||
"PromiseDebugging.webidl",
|
||||
"SessionStoreUtils.webidl",
|
||||
|
|
|
@ -167,4 +167,8 @@ void PermissionStatus::DisconnectFromOwner() {
|
|||
DOMEventTargetHelper::DisconnectFromOwner();
|
||||
}
|
||||
|
||||
void PermissionStatus::GetType(nsACString& aName) const {
|
||||
aName.Assign(GetPermissionType());
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
|
|
@ -29,6 +29,7 @@ class PermissionStatus : public DOMEventTargetHelper {
|
|||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
PermissionState State() const { return mState; }
|
||||
void SetState(PermissionState aState) { mState = aState; }
|
||||
|
||||
IMPL_EVENT_HANDLER(change)
|
||||
|
||||
|
@ -36,6 +37,8 @@ class PermissionStatus : public DOMEventTargetHelper {
|
|||
|
||||
PermissionName Name() const { return mName; }
|
||||
|
||||
void GetType(nsACString& aName) const;
|
||||
|
||||
RefPtr<SimplePromise> Init();
|
||||
|
||||
protected:
|
||||
|
|
|
@ -6,16 +6,14 @@
|
|||
|
||||
#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/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 "mozilla/Components.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
#include "PermissionUtils.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
@ -143,4 +141,42 @@ already_AddRefed<Promise> Permissions::Query(JSContext* aCx,
|
|||
return promise.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<PermissionStatus> Permissions::ParseSetParameters(
|
||||
JSContext* aCx, JS::Handle<JSObject*> 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.
|
||||
// (The error type should be handled by the caller)
|
||||
JS::Rooted<JS::Value> parameters(aCx, JS::ObjectValue(*aParameters));
|
||||
RootedDictionary<PermissionSetParameters> parametersDict(aCx);
|
||||
if (!parametersDict.Init(aCx, parameters)) {
|
||||
aRv.MightThrowJSException();
|
||||
aRv.StealExceptionFromJSContext(aCx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 2: Let rootDesc be parameters.descriptor.
|
||||
JS::Rooted<JSObject*> rootDesc(aCx, parametersDict.mDescriptor);
|
||||
|
||||
// Step 3: If parameters.state is an inappropriate permission state for any
|
||||
// implementation-defined reason, return a invalid argument error.
|
||||
// (We don't do this)
|
||||
|
||||
// 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<PermissionStatus> 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(parametersDict.mState);
|
||||
|
||||
return status.forget();
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
|
|
@ -18,6 +18,7 @@ class ErrorResult;
|
|||
namespace dom {
|
||||
|
||||
class Promise;
|
||||
class PermissionStatus;
|
||||
|
||||
class Permissions final : public nsISupports, public nsWrapperCache {
|
||||
public:
|
||||
|
@ -35,6 +36,11 @@ class Permissions final : public nsISupports, public nsWrapperCache {
|
|||
JS::Handle<JSObject*> aPermission,
|
||||
ErrorResult& aRv);
|
||||
|
||||
// The IDL conversion steps of
|
||||
// https://w3c.github.io/permissions/#webdriver-command-set-permission
|
||||
already_AddRefed<PermissionStatus> ParseSetParameters(
|
||||
JSContext* aCx, JS::Handle<JSObject*> aParameters, ErrorResult& aRv);
|
||||
|
||||
private:
|
||||
~Permissions();
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ EXPORTS.mozilla.dom += [
|
|||
"MidiPermissionStatus.h",
|
||||
"Permissions.h",
|
||||
"PermissionStatus.h",
|
||||
"PermissionUtils.h",
|
||||
"StorageAccessPermissionStatus.h",
|
||||
]
|
||||
|
||||
|
|
|
@ -18,4 +18,7 @@ interface PermissionStatus : EventTarget {
|
|||
readonly attribute PermissionName name;
|
||||
readonly attribute PermissionState state;
|
||||
attribute EventHandler onchange;
|
||||
|
||||
[ChromeOnly]
|
||||
readonly attribute UTF8String type;
|
||||
};
|
||||
|
|
|
@ -35,4 +35,10 @@ dictionary MidiPermissionDescriptor : PermissionDescriptor {
|
|||
interface Permissions {
|
||||
[NewObject]
|
||||
Promise<PermissionStatus> query(object permission);
|
||||
|
||||
// http://w3c.github.io/permissions/#webdriver-command-set-permission
|
||||
// We use `object` instead of PermissionSetParameters here to retain the access
|
||||
// to the extra descriptor members from e.g. MidiPermissionDescriptor.
|
||||
[ChromeOnly, Throws]
|
||||
PermissionStatus parseSetParameters(object parameters);
|
||||
};
|
||||
|
|
|
@ -3382,28 +3382,20 @@ GeckoDriver.prototype.setPermission = async function (cmd) {
|
|||
);
|
||||
}
|
||||
|
||||
// This abuses permissions.query() to do the IDL conversion in step 1 in the spec:
|
||||
// https://w3c.github.io/permissions/#webdriver-command-set-permission
|
||||
// If this does not throw then the descriptor is valid.
|
||||
//
|
||||
// TODO: Currently we consume the original JS object later on, but we should
|
||||
// consume the IDL-converted dictionary instead.
|
||||
// For WPT purpose the current state is fine, but for general webdriver extension
|
||||
// this is not ideal as the script might get access to fields that are not in IDL.
|
||||
// See bug 1876754.
|
||||
let params;
|
||||
try {
|
||||
await this.curBrowser.window.navigator.permissions.query(descriptor);
|
||||
params =
|
||||
await this.curBrowser.window.navigator.permissions.parseSetParameters({
|
||||
descriptor,
|
||||
state,
|
||||
});
|
||||
} catch (err) {
|
||||
throw new lazy.error.InvalidArgumentError(`setPermission: ${err.message}`);
|
||||
}
|
||||
|
||||
lazy.assert.boolean(oneRealm);
|
||||
lazy.assert.that(
|
||||
state => ["granted", "denied", "prompt"].includes(state),
|
||||
`state is ${state}, expected "granted", "denied", or "prompt"`
|
||||
)(state);
|
||||
|
||||
lazy.permissions.set(descriptor, state, oneRealm, browsingContext);
|
||||
lazy.permissions.set(params.type, params.state, oneRealm, browsingContext);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -12,18 +12,11 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
|||
/** @namespace */
|
||||
export const permissions = {};
|
||||
|
||||
const specialPermissionNameMap = {
|
||||
geolocation: "geo",
|
||||
notifications: "desktop-notification",
|
||||
};
|
||||
|
||||
function mapToInternalPermissionParameters(browsingContext, descriptor) {
|
||||
function mapToInternalPermissionParameters(browsingContext, permissionType) {
|
||||
const currentURI = browsingContext.currentWindowGlobal.documentURI;
|
||||
|
||||
const { name } = descriptor;
|
||||
|
||||
// storage-access is quite special...
|
||||
if (name === "storage-access") {
|
||||
if (permissionType === "storage-access") {
|
||||
const thirdPartyPrincipalSite = Services.eTLD.getSite(currentURI);
|
||||
|
||||
const topLevelURI = browsingContext.top.currentWindowGlobal.documentURI;
|
||||
|
@ -39,15 +32,8 @@ function mapToInternalPermissionParameters(browsingContext, descriptor) {
|
|||
const currentPrincipal =
|
||||
Services.scriptSecurityManager.createContentPrincipal(currentURI, {});
|
||||
|
||||
if (name === "midi" && descriptor.sysex) {
|
||||
return {
|
||||
name: "midi-sysex",
|
||||
principal: currentPrincipal,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
name: specialPermissionNameMap[name] ?? name,
|
||||
name: permissionType,
|
||||
principal: currentPrincipal,
|
||||
};
|
||||
}
|
||||
|
@ -56,8 +42,8 @@ function mapToInternalPermissionParameters(browsingContext, descriptor) {
|
|||
* Set a permission's state.
|
||||
* Note: Currently just a shim to support testdriver's set_permission.
|
||||
*
|
||||
* @param {object} descriptor
|
||||
* Descriptor with the `name` property.
|
||||
* @param {object} permissionType
|
||||
* The Gecko internal permission type
|
||||
* @param {string} state
|
||||
* State of the permission. It can be `granted`, `denied` or `prompt`.
|
||||
* @param {boolean} oneRealm
|
||||
|
@ -68,7 +54,7 @@ function mapToInternalPermissionParameters(browsingContext, descriptor) {
|
|||
* If `marionette.setpermission.enabled` is not set or
|
||||
* an unsupported permission is used.
|
||||
*/
|
||||
permissions.set = function (descriptor, state, oneRealm, browsingContext) {
|
||||
permissions.set = function (permissionType, state, oneRealm, browsingContext) {
|
||||
if (!lazy.MarionettePrefs.setPermissionEnabled) {
|
||||
throw new lazy.error.UnsupportedOperationError(
|
||||
"'Set Permission' is not available"
|
||||
|
@ -77,7 +63,7 @@ permissions.set = function (descriptor, state, oneRealm, browsingContext) {
|
|||
|
||||
const { name, principal } = mapToInternalPermissionParameters(
|
||||
browsingContext,
|
||||
descriptor
|
||||
permissionType
|
||||
);
|
||||
|
||||
switch (state) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче