зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1560570- FeaturePolicy should be considered when permissions.query() is called r=baku,johannh
Differential Revision: https://phabricator.services.mozilla.com/D44210 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
ced80473dd
Коммит
cf867199bc
|
@ -83,6 +83,7 @@
|
|||
#include "nsINSSErrorsService.h"
|
||||
#include "nsISocketProvider.h"
|
||||
#include "nsISiteSecurityService.h"
|
||||
#include "PermissionDelegateHandler.h"
|
||||
|
||||
#include "mozilla/AsyncEventDispatcher.h"
|
||||
#include "mozilla/BasicEvents.h"
|
||||
|
@ -1906,6 +1907,10 @@ Document::~Document() {
|
|||
mXULPersist->DropDocumentReference();
|
||||
}
|
||||
|
||||
if (mPermissionDelegateHandler) {
|
||||
mPermissionDelegateHandler->DropDocumentReference();
|
||||
}
|
||||
|
||||
delete mHeaderData;
|
||||
|
||||
mPendingTitleChangeEvent.Revoke();
|
||||
|
@ -15366,6 +15371,14 @@ void Document::AddResizeObserver(ResizeObserver* aResizeObserver) {
|
|||
mResizeObserverController->AddResizeObserver(aResizeObserver);
|
||||
}
|
||||
|
||||
PermissionDelegateHandler* Document::GetPermissionDelegateHandler() {
|
||||
if (!mPermissionDelegateHandler) {
|
||||
mPermissionDelegateHandler =
|
||||
mozilla::MakeAndAddRef<PermissionDelegateHandler>(this);
|
||||
}
|
||||
return mPermissionDelegateHandler;
|
||||
}
|
||||
|
||||
void Document::ScheduleResizeObserversNotification() const {
|
||||
if (!mResizeObserverController) {
|
||||
return;
|
||||
|
|
|
@ -134,6 +134,7 @@ class nsIGlobalObject;
|
|||
class nsIXULWindow;
|
||||
class nsXULPrototypeDocument;
|
||||
class nsXULPrototypeElement;
|
||||
class PermissionDelegateHandler;
|
||||
struct nsFont;
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -3970,6 +3971,9 @@ class Document : public nsINode,
|
|||
void AddResizeObserver(ResizeObserver* aResizeObserver);
|
||||
void ScheduleResizeObserversNotification() const;
|
||||
|
||||
// Getter for PermissionDelegateHandler. Performs lazy initialization.
|
||||
PermissionDelegateHandler* GetPermissionDelegateHandler();
|
||||
|
||||
/**
|
||||
* Localization
|
||||
*
|
||||
|
@ -4596,6 +4600,10 @@ class Document : public nsINode,
|
|||
|
||||
UniquePtr<ResizeObserverController> mResizeObserverController;
|
||||
|
||||
// Permission Delegate Handler, lazily-initialized in
|
||||
// PermissionDelegateHandler
|
||||
RefPtr<PermissionDelegateHandler> mPermissionDelegateHandler;
|
||||
|
||||
// True if BIDI is enabled.
|
||||
bool mBidiEnabled : 1;
|
||||
// True if we may need to recompute the language prefs for this document.
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "PermissionObserver.h"
|
||||
#include "PermissionUtils.h"
|
||||
#include "nsPermission.h"
|
||||
#include "PermissionDelegateHandler.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -64,19 +65,22 @@ JSObject* PermissionStatus::WrapObject(JSContext* aCx,
|
|||
}
|
||||
|
||||
nsresult PermissionStatus::UpdateState() {
|
||||
nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
|
||||
if (NS_WARN_IF(!permMgr)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = GetOwner();
|
||||
if (NS_WARN_IF(!window)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
RefPtr<Document> document = window->GetExtantDoc();
|
||||
if (NS_WARN_IF(!document)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
uint32_t action = nsIPermissionManager::DENY_ACTION;
|
||||
nsresult rv = permMgr->TestPermissionFromWindow(
|
||||
window, PermissionNameToType(mName), &action);
|
||||
|
||||
PermissionDelegateHandler* permissionHandler =
|
||||
document->GetPermissionDelegateHandler();
|
||||
nsresult rv = permissionHandler->GetPermissionForPermissionsAPI(
|
||||
PermissionNameToType(mName), &action);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
[DEFAULT]
|
||||
support-files =
|
||||
file_empty.html
|
||||
prefs =
|
||||
dom.security.featurePolicy.enabled=true
|
||||
dom.security.featurePolicy.header.enabled=true
|
||||
dom.security.featurePolicy.webidl.enabled=true
|
||||
|
||||
[test_cross_origin_iframe.html]
|
||||
[test_permissions_api.html]
|
||||
|
|
|
@ -0,0 +1,239 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Permissions API</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<pre id="test"></pre>
|
||||
<script type="application/javascript">
|
||||
/*globals SpecialPowers, SimpleTest, is, ok, */
|
||||
'use strict';
|
||||
|
||||
function setPermission(type, allow) {
|
||||
return new Promise(resolve => {
|
||||
SpecialPowers.popPermissions(() => {
|
||||
SpecialPowers.pushPermissions(
|
||||
[{ type, allow, context: document }],
|
||||
resolve
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function checkPermission(aWindow, aExpectedState, aName) {
|
||||
return SpecialPowers.wrap(aWindow).navigator.permissions
|
||||
.query({ name: aName })
|
||||
.then(
|
||||
result => is(SpecialPowers.wrap(result).state, aExpectedState, `correct state for '${aName}'`),
|
||||
() => ok(false, `query should not have rejected for '${aName}'`)
|
||||
);
|
||||
}
|
||||
|
||||
function createIframe(aId, aAllow) {
|
||||
return new Promise((resolve) => {
|
||||
const iframe = document.createElement('iframe');
|
||||
iframe.id = aId;
|
||||
iframe.src = 'https://example.org/tests/dom/permission/tests/file_empty.html';
|
||||
if (aAllow) {
|
||||
iframe.allow = aAllow;
|
||||
}
|
||||
iframe.onload = () => resolve(iframe.contentWindow);
|
||||
document.body.appendChild(iframe);
|
||||
});
|
||||
}
|
||||
|
||||
function removeIframe(aId) {
|
||||
return new Promise((resolve) => {
|
||||
document.body.removeChild(document.getElementById(aId));
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
const {
|
||||
UNKNOWN_ACTION,
|
||||
PROMPT_ACTION,
|
||||
ALLOW_ACTION,
|
||||
DENY_ACTION
|
||||
} = SpecialPowers.Ci.nsIPermissionManager;
|
||||
|
||||
const tests = [
|
||||
{
|
||||
id: 'query navigation top unknown',
|
||||
top: UNKNOWN_ACTION,
|
||||
name: 'geolocation',
|
||||
type: 'geo',
|
||||
expected: 'denied',
|
||||
},
|
||||
{
|
||||
id: 'query notifications top unknown',
|
||||
top: UNKNOWN_ACTION,
|
||||
name: 'notifications',
|
||||
type: 'desktop-notification',
|
||||
expected: 'denied',
|
||||
},
|
||||
{
|
||||
id: 'query push top unknown',
|
||||
top: UNKNOWN_ACTION,
|
||||
name: 'push',
|
||||
type: 'desktop-notification',
|
||||
expected: 'denied',
|
||||
},
|
||||
{
|
||||
id: 'query persistent-storage unknown',
|
||||
top: UNKNOWN_ACTION,
|
||||
name: 'persistent-storage',
|
||||
type: 'persistent-storage',
|
||||
expected: 'prompt',
|
||||
},
|
||||
{
|
||||
id: 'query navigation top prompt',
|
||||
top: PROMPT_ACTION,
|
||||
name: 'geolocation',
|
||||
type: 'geo',
|
||||
expected: 'denied',
|
||||
},
|
||||
{
|
||||
id: 'query notifications top prompt',
|
||||
top: PROMPT_ACTION,
|
||||
name: 'notifications',
|
||||
type: 'desktop-notification',
|
||||
expected: 'denied',
|
||||
},
|
||||
{
|
||||
id: 'query push top prompt',
|
||||
top: PROMPT_ACTION,
|
||||
name: 'push',
|
||||
type: 'desktop-notification',
|
||||
expected: 'denied',
|
||||
},
|
||||
{
|
||||
id: 'query persistent-storage top prompt',
|
||||
top: PROMPT_ACTION,
|
||||
name: 'persistent-storage',
|
||||
type: 'persistent-storage',
|
||||
expected: 'prompt',
|
||||
},
|
||||
{
|
||||
id: 'query navigation top denied',
|
||||
top: DENY_ACTION,
|
||||
name: 'geolocation',
|
||||
type: 'geo',
|
||||
expected: 'denied',
|
||||
},
|
||||
{
|
||||
id: 'query notifications top denied',
|
||||
top: DENY_ACTION,
|
||||
name: 'notifications',
|
||||
type: 'desktop-notification',
|
||||
expected: 'denied',
|
||||
},
|
||||
{
|
||||
id: 'query push top denied',
|
||||
top: DENY_ACTION,
|
||||
name: 'push',
|
||||
type: 'desktop-notification',
|
||||
expected: 'denied',
|
||||
},
|
||||
{
|
||||
id: 'query persistent-storage top denied',
|
||||
top: DENY_ACTION,
|
||||
name: 'persistent-storage',
|
||||
type: 'persistent-storage',
|
||||
expected: 'prompt',
|
||||
},
|
||||
{
|
||||
id: 'query navigation top granted',
|
||||
top: ALLOW_ACTION,
|
||||
name: 'geolocation',
|
||||
type: 'geo',
|
||||
expected: 'denied',
|
||||
},
|
||||
{
|
||||
id: 'query notifications top granted',
|
||||
top: ALLOW_ACTION,
|
||||
name: 'notifications',
|
||||
type: 'desktop-notification',
|
||||
expected: 'denied',
|
||||
},
|
||||
{
|
||||
id: 'query push top granted',
|
||||
top: ALLOW_ACTION,
|
||||
name: 'push',
|
||||
type: 'desktop-notification',
|
||||
expected: 'denied',
|
||||
},
|
||||
{
|
||||
id: 'query persistent-storage top granted',
|
||||
top: ALLOW_ACTION,
|
||||
name: 'persistent-storage',
|
||||
type: 'persistent-storage',
|
||||
expected: 'prompt',
|
||||
},
|
||||
{
|
||||
id: 'query navigation top denied, iframe has allow attribute',
|
||||
top: DENY_ACTION,
|
||||
allow: 'geolocation',
|
||||
name: 'geolocation',
|
||||
type: 'geo',
|
||||
expected: 'denied',
|
||||
},
|
||||
{
|
||||
id: 'query navigation top granted, iframe has allow attribute',
|
||||
top: ALLOW_ACTION,
|
||||
allow: 'geolocation',
|
||||
name: 'geolocation',
|
||||
type: 'geo',
|
||||
expected: 'granted',
|
||||
},
|
||||
{
|
||||
id: 'query navigation top prompt, iframe has allow attribute',
|
||||
top: PROMPT_ACTION,
|
||||
allow: 'geolocation',
|
||||
name: 'geolocation',
|
||||
type: 'geo',
|
||||
expected: 'prompt',
|
||||
},
|
||||
{
|
||||
id: 'query navigation top unknown, iframe has allow attribute',
|
||||
top: UNKNOWN_ACTION,
|
||||
allow: 'geolocation',
|
||||
name: 'geolocation',
|
||||
type: 'geo',
|
||||
expected: 'prompt',
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
async function nextTest() {
|
||||
if (tests.length == 0) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
let test = tests.shift();
|
||||
await setPermission(test.type, test.top)
|
||||
.then(() => createIframe(test.id, test.allow))
|
||||
.then(contentWindow => checkPermission(contentWindow, test.expected, test.name))
|
||||
.then(() => removeIframe(test.id));
|
||||
|
||||
SimpleTest.executeSoon(nextTest);
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["permissions.delegation.enable", true],
|
||||
]}).then(nextTest);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,117 @@
|
|||
/* -*- Mode: C++; tab-width: 2; 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 "nsGlobalWindowInner.h"
|
||||
#include "PermissionDelegateHandler.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
#include "nsIPrincipal.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "mozilla/dom/FeaturePolicyUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
typedef PermissionDelegateHandler::PermissionDelegatePolicy DelegatePolicy;
|
||||
typedef PermissionDelegateHandler::PermissionDelegateInfo DelegateInfo;
|
||||
|
||||
// Particular type of permissions to care about. We decide cases by case and
|
||||
// give various types of controls over each of these.
|
||||
static const DelegateInfo sPermissionsMap[] = {
|
||||
// Permissions API map
|
||||
{"geo", u"geolocation", DelegatePolicy::eDelegateUseFeaturePolicy},
|
||||
{"desktop-notification", nullptr,
|
||||
DelegatePolicy::ePersistDeniedCrossOrigin},
|
||||
{"persistent-storage", nullptr, DelegatePolicy::eDelegateUseIframeOrigin},
|
||||
};
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION(PermissionDelegateHandler)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(PermissionDelegateHandler)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(PermissionDelegateHandler)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PermissionDelegateHandler)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
PermissionDelegateHandler::PermissionDelegateHandler(dom::Document* aDocument)
|
||||
: mDocument(aDocument) {
|
||||
MOZ_ASSERT(aDocument);
|
||||
}
|
||||
|
||||
const DelegateInfo* PermissionDelegateHandler::GetPermissionDelegateInfo(
|
||||
const nsAString& aPermissionName) const {
|
||||
nsAutoString lowerContent(aPermissionName);
|
||||
ToLowerCase(lowerContent);
|
||||
|
||||
for (const auto& perm : sPermissionsMap) {
|
||||
if (lowerContent.EqualsASCII(perm.mPermissionName)) {
|
||||
return &perm;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsresult PermissionDelegateHandler::GetPermissionForPermissionsAPI(
|
||||
const nsACString& aType, uint32_t* aPermission) {
|
||||
MOZ_ASSERT(mDocument);
|
||||
|
||||
const DelegateInfo* info =
|
||||
GetPermissionDelegateInfo(NS_ConvertUTF8toUTF16(aType));
|
||||
|
||||
// If the type is not in the supported list, auto denied
|
||||
if (!info) {
|
||||
*aPermission = nsIPermissionManager::DENY_ACTION;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPermissionManager> permMgr =
|
||||
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
*aPermission = nsIPermissionManager::DENY_ACTION;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal = mDocument->NodePrincipal();
|
||||
if (!Preferences::GetBool("permissions.delegation.enable", false)) {
|
||||
return permMgr->TestPermissionFromPrincipal(principal, aType, aPermission);
|
||||
}
|
||||
|
||||
if (info->mPolicy == DelegatePolicy::eDelegateUseIframeOrigin) {
|
||||
return permMgr->TestPermissionFromPrincipal(principal, aType, aPermission);
|
||||
}
|
||||
|
||||
nsPIDOMWindowInner* window = mDocument->GetInnerWindow();
|
||||
nsGlobalWindowInner* innerWindow = nsGlobalWindowInner::Cast(window);
|
||||
nsIPrincipal* topPrincipal = innerWindow->GetTopLevelPrincipal();
|
||||
|
||||
// Permission is delegated in same origin
|
||||
if (principal->Subsumes(topPrincipal)) {
|
||||
return permMgr->TestPermissionFromPrincipal(topPrincipal, aType,
|
||||
aPermission);
|
||||
}
|
||||
|
||||
if (info->mPolicy == DelegatePolicy::ePersistDeniedCrossOrigin) {
|
||||
*aPermission = nsIPermissionManager::DENY_ACTION;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (info->mPolicy == DelegatePolicy::eDelegateUseFeaturePolicy &&
|
||||
info->mFeatureName) {
|
||||
nsAutoString featureName(info->mFeatureName);
|
||||
// Default allowlist for a feature used in permissions delegate should be
|
||||
// set to eSelf, to ensure that permission is denied by default and only
|
||||
// have the opportunity to request permission with allow attribute.
|
||||
if (!FeaturePolicyUtils::IsFeatureAllowed(mDocument, featureName)) {
|
||||
*aPermission = nsIPermissionManager::DENY_ACTION;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return permMgr->TestPermissionFromPrincipal(topPrincipal, aType, aPermission);
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
/* -*- Mode: C++; tab-width: 2; 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/. */
|
||||
|
||||
/*
|
||||
* Permission delegate handler provides a policy of how top-level can
|
||||
* delegate permission to embedded iframes.
|
||||
*
|
||||
* This class includes a mechanism to delegate permission using feature
|
||||
* policy. Feature policy will assure that only cross-origin iframes which
|
||||
* have been explicitly granted access will have the opportunity to request
|
||||
* permission.
|
||||
*
|
||||
* For example if an iframe has not been granted access to geolocation by
|
||||
* Feature Policy, geolocation request from the iframe will be automatically
|
||||
* denied. if the top-level origin already has access to geolocation and the
|
||||
* iframe has been granted access to geolocation by Feature Policy, the iframe
|
||||
* will also have access to geolocation. If the top-level frame did not have
|
||||
* access to geolocation, and the iframe has been granted access to geolocation
|
||||
* by Feature Policy, a request from the cross-origin iframe would trigger a
|
||||
* prompt using of the top-level origin.
|
||||
*/
|
||||
|
||||
#ifndef PermissionDelegateHandler_h__
|
||||
#define PermissionDelegateHandler_h__
|
||||
|
||||
#include "nsISupports.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class Document;
|
||||
}
|
||||
} // namespace mozilla
|
||||
|
||||
class PermissionDelegateHandler final : nsISupports {
|
||||
public:
|
||||
explicit PermissionDelegateHandler(mozilla::dom::Document* aDocument);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(PermissionDelegateHandler)
|
||||
|
||||
/*
|
||||
* Get permission state for permission api with aType, which applied
|
||||
* permission delegate policy.
|
||||
*/
|
||||
nsresult GetPermissionForPermissionsAPI(const nsACString& aType,
|
||||
uint32_t* aPermission);
|
||||
|
||||
enum PermissionDelegatePolicy {
|
||||
/* Always delegate permission from top level to iframe and the iframe
|
||||
* should use top level origin to get/set permission.*/
|
||||
eDelegateUseTopOrigin,
|
||||
|
||||
/* Permission is delegated using Feature Policy. Permission is denied by
|
||||
* default in cross origin iframe and the iframe only could get/set
|
||||
* permission if there's allow attribute set in iframe. e.g allow =
|
||||
* "geolocation" */
|
||||
eDelegateUseFeaturePolicy,
|
||||
|
||||
/* Persistent denied permissions in cross origin iframe */
|
||||
ePersistDeniedCrossOrigin,
|
||||
|
||||
/* This is the old behavior of cross origin iframe permission. The
|
||||
* permission delegation should not have an effect on iframe. The cross
|
||||
* origin iframe get/set permissions by its origin */
|
||||
eDelegateUseIframeOrigin,
|
||||
};
|
||||
|
||||
/*
|
||||
* Indicates matching between Feature Policy and Permissions name defined in
|
||||
* Permissions Manager, not DOM Permissions API. Permissions API exposed in
|
||||
* DOM only supports "geo" at the moment but Permissions Manager also supports
|
||||
* "camera", "microphone".
|
||||
*/
|
||||
typedef struct {
|
||||
const char* mPermissionName;
|
||||
const char16_t* mFeatureName;
|
||||
PermissionDelegatePolicy mPolicy;
|
||||
} PermissionDelegateInfo;
|
||||
|
||||
/**
|
||||
* The loader maintains a weak reference to the document with
|
||||
* which it is initialized. This call forces the reference to
|
||||
* be dropped.
|
||||
*/
|
||||
void DropDocumentReference() { mDocument = nullptr; }
|
||||
|
||||
private:
|
||||
virtual ~PermissionDelegateHandler() = default;
|
||||
|
||||
/*
|
||||
* Helper function to return the delegate info value for aPermissionName.
|
||||
*/
|
||||
const PermissionDelegateInfo* GetPermissionDelegateInfo(
|
||||
const nsAString& aPermissionName) const;
|
||||
|
||||
// A weak pointer to our document. Nulled out by DropDocumentReference.
|
||||
mozilla::dom::Document* mDocument;
|
||||
};
|
||||
|
||||
#endif // PermissionDelegateHandler_h__
|
|
@ -10,10 +10,15 @@ TESTING_JS_MODULES += [
|
|||
'test/PermissionTestUtils.jsm',
|
||||
]
|
||||
|
||||
EXPORTS += [
|
||||
'PermissionDelegateHandler.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'nsContentBlocker.cpp',
|
||||
'nsPermission.cpp',
|
||||
'nsPermissionManager.cpp',
|
||||
'PermissionDelegateHandler.cpp',
|
||||
]
|
||||
|
||||
XPCOM_MANIFESTS += [
|
||||
|
|
|
@ -6499,6 +6499,15 @@
|
|||
value: 5000
|
||||
mirror: always
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Prefs starting with "permissions."
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
- name: permissions.delegation.enable
|
||||
type: bool
|
||||
value: @IS_NIGHTLY_BUILD@
|
||||
mirror: always
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Prefs starting with "plain_text."
|
||||
#---------------------------------------------------------------------------
|
||||
|
|
|
@ -61,6 +61,7 @@ pref_groups = [
|
|||
'network',
|
||||
'nglayout',
|
||||
'page_load',
|
||||
'permissions',
|
||||
'plain_text',
|
||||
'plugins',
|
||||
'preferences',
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
prefs: [permissions.delegation.enable:true, dom.security.featurePolicy.enabled:true, dom.security.featurePolicy.header.enabled:true, dom.security.featurePolicy.webidl.enabled:true]
|
|
@ -0,0 +1,11 @@
|
|||
<script>
|
||||
'use strict';
|
||||
|
||||
Promise.resolve().then(() => navigator.permissions.query({name:'geolocation'}))
|
||||
.then(permissionStatus => {
|
||||
window.parent.postMessage({ state: permissionStatus.state }, '*');
|
||||
}, error => {
|
||||
window.parent.postMessage({ state: null }, '*');
|
||||
});
|
||||
</script>
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>Test permissions query againts feature policy allow attribute</title>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<div id="log"></div>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
function test_permissions_query(
|
||||
feature_description, test, src, expect_state, allow_attribute) {
|
||||
let frame = document.createElement('iframe');
|
||||
frame.src = src;
|
||||
|
||||
if (typeof allow_attribute !== 'undefined') {
|
||||
frame.allow = allow_attribute;
|
||||
}
|
||||
|
||||
window.addEventListener('message', test.step_func(function handler(evt) {
|
||||
if (evt.source === frame.contentWindow) {
|
||||
assert_equals(evt.data.state, expect_state, feature_description);
|
||||
document.body.removeChild(frame);
|
||||
window.removeEventListener('message', handler);
|
||||
test.done();
|
||||
}
|
||||
}));
|
||||
|
||||
document.body.appendChild(frame);
|
||||
}
|
||||
|
||||
const same_origin_src =
|
||||
"/permissions/feature-policy-permissions-query.html";
|
||||
const cross_origin_src =
|
||||
"https://{{domains[www]}}:{{ports[https][0]}}" + same_origin_src;
|
||||
|
||||
async_test(t => {
|
||||
test_permissions_query(
|
||||
'navigator.permissions.query("geolocation")',
|
||||
t,
|
||||
same_origin_src,
|
||||
"prompt",
|
||||
"geolocation"
|
||||
);
|
||||
}, 'Permissions.state is "prompt" with allow="geolocation" in same-origin iframes.');
|
||||
|
||||
async_test(t => {
|
||||
test_permissions_query(
|
||||
'navigator.permissions.query("geolocation")',
|
||||
t,
|
||||
cross_origin_src,
|
||||
"prompt",
|
||||
"geolocation"
|
||||
);
|
||||
}, 'Permissions.state is "prompt" with allow="geolocation" in cross-origin iframes.');
|
||||
|
||||
async_test(t => {
|
||||
test_permissions_query(
|
||||
'navigator.permissions.query("geolocation")',
|
||||
t,
|
||||
same_origin_src,
|
||||
"prompt"
|
||||
);
|
||||
}, 'Permission.state is "prompt" in same-origin iframes.');
|
||||
|
||||
async_test(t => {
|
||||
test_permissions_query(
|
||||
'navigator.permissions.query("geolocation")',
|
||||
t,
|
||||
cross_origin_src,
|
||||
"denied"
|
||||
);
|
||||
}, 'Permission.state is "denied" in cross-origin iframes.');
|
||||
|
||||
</script>
|
Загрузка…
Ссылка в новой задаче