зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 2 changesets (bug 1580567, bug 1599927
) for mochitest failures at test_interfaces.html. CLOSED TREE
Backed out changeset 0e0d88942d33 (bug 1599927
)
Backed out changeset 522c8d183bd5 (bug 1580567)
--HG--
rename : browser/components/privatebrowsing/test/browser/browser_privatebrowsing_rememberprompt.js => browser/components/privatebrowsing/test/browser/browser_privatebrowsing_geoprompt.js
This commit is contained in:
Родитель
3a3fa7f977
Коммит
9c36dcbf23
|
@ -402,7 +402,6 @@ pref("permissions.manager.defaultsUrl", "resource://app/defaults/permissions");
|
|||
pref("permissions.default.camera", 0);
|
||||
pref("permissions.default.microphone", 0);
|
||||
pref("permissions.default.geo", 0);
|
||||
pref("permissions.default.xr", 0);
|
||||
pref("permissions.default.desktop-notification", 0);
|
||||
pref("permissions.default.shortcuts", 0);
|
||||
|
||||
|
@ -817,7 +816,6 @@ pref("gecko.handlerService.schemes.ircs.3.name", "chrome://browser-region/locale
|
|||
pref("gecko.handlerService.schemes.ircs.3.uriTemplate", "chrome://browser-region/locale/region.properties");
|
||||
|
||||
pref("browser.geolocation.warning.infoURL", "https://www.mozilla.org/%LOCALE%/firefox/geolocation/");
|
||||
pref("browser.xr.warning.infoURL", "https://www.mozilla.org/%LOCALE%/firefox/xr/");
|
||||
|
||||
pref("browser.sessionstore.resume_from_crash", true);
|
||||
pref("browser.sessionstore.resume_session_once", false);
|
||||
|
|
|
@ -290,11 +290,6 @@ var gIdentityHandler = {
|
|||
return (this._geoSharingIcon = document.getElementById("geo-sharing-icon"));
|
||||
},
|
||||
|
||||
get _xrSharingIcon() {
|
||||
delete this._xrSharingIcon;
|
||||
return (this._xrSharingIcon = document.getElementById("xr-sharing-icon"));
|
||||
},
|
||||
|
||||
get _webRTCSharingIcon() {
|
||||
delete this._webRTCSharingIcon;
|
||||
return (this._webRTCSharingIcon = document.getElementById(
|
||||
|
@ -577,7 +572,6 @@ var gIdentityHandler = {
|
|||
this._webRTCSharingIcon.removeAttribute("paused");
|
||||
this._webRTCSharingIcon.removeAttribute("sharing");
|
||||
this._geoSharingIcon.removeAttribute("sharing");
|
||||
this._xrSharingIcon.removeAttribute("sharing");
|
||||
|
||||
if (this._sharingState) {
|
||||
if (
|
||||
|
@ -597,9 +591,6 @@ var gIdentityHandler = {
|
|||
if (this._sharingState.geo) {
|
||||
this._geoSharingIcon.setAttribute("sharing", this._sharingState.geo);
|
||||
}
|
||||
if (this._sharingState.xr) {
|
||||
this._xrSharingIcon.setAttribute("sharing", this._sharingState.xr);
|
||||
}
|
||||
}
|
||||
|
||||
if (this._identityPopup.state == "open") {
|
||||
|
@ -1354,20 +1345,6 @@ var gIdentityHandler = {
|
|||
}
|
||||
}
|
||||
|
||||
if (this._sharingState && this._sharingState.xr) {
|
||||
let xrPermission = permissions.find(perm => perm.id === "xr");
|
||||
if (xrPermission) {
|
||||
xrPermission.sharingState = true;
|
||||
} else {
|
||||
permissions.push({
|
||||
id: "xr",
|
||||
state: SitePermissions.ALLOW,
|
||||
scope: SitePermissions.SCOPE_REQUEST,
|
||||
sharingState: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (this._sharingState && this._sharingState.webRTC) {
|
||||
let webrtcState = this._sharingState.webRTC;
|
||||
// If WebRTC device or screen permissions are in use, we need to find
|
||||
|
@ -1595,12 +1572,9 @@ var gIdentityHandler = {
|
|||
return container;
|
||||
}
|
||||
|
||||
if (aPermission.id == "geo" || aPermission.id == "xr") {
|
||||
if (aPermission.id == "geo") {
|
||||
let block = document.createXULElement("vbox");
|
||||
block.setAttribute(
|
||||
"id",
|
||||
"identity-popup-" + aPermission.id + "-container"
|
||||
);
|
||||
block.setAttribute("id", "identity-popup-geo-container");
|
||||
|
||||
let button = this._createPermissionClearButton(aPermission, block);
|
||||
container.appendChild(button);
|
||||
|
@ -1634,8 +1608,8 @@ var gIdentityHandler = {
|
|||
let browser = gBrowser.selectedBrowser;
|
||||
this._permissionList.removeChild(container);
|
||||
if (aPermission.sharingState) {
|
||||
if (aPermission.id === "geo" || aPermission.id === "xr") {
|
||||
let origins = browser.getDevicePermissionOrigins(aPermission.id);
|
||||
if (aPermission.id === "geo") {
|
||||
let origins = browser.getDevicePermissionOrigins("geo");
|
||||
for (let origin of origins) {
|
||||
let principal = Services.scriptSecurityManager.createContentPrincipalFromOrigin(
|
||||
origin
|
||||
|
@ -1690,8 +1664,6 @@ var gIdentityHandler = {
|
|||
|
||||
if (aPermission.id === "geo") {
|
||||
gBrowser.updateBrowserSharing(browser, { geo: false });
|
||||
} else if (aPermission.id === "xr") {
|
||||
gBrowser.updateBrowserSharing(browser, { xr: false });
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -888,13 +888,10 @@
|
|||
<box style="pointer-events: none;">
|
||||
<image class="sharing-icon" id="webrtc-sharing-icon"/>
|
||||
<image class="sharing-icon geo-icon" id="geo-sharing-icon"/>
|
||||
<image class="sharing-icon xr-icon" id="xr-sharing-icon"/>
|
||||
</box>
|
||||
<box id="blocked-permissions-container" align="center">
|
||||
<image data-permission-id="geo" class="blocked-permission-icon geo-icon" role="button"
|
||||
data-l10n-id="urlbar-geolocation-blocked"/>
|
||||
<image data-permission-id="xr" class="blocked-permission-icon xr-icon" role="button"
|
||||
data-l10n-id="urlbar-xr-blocked"/>
|
||||
<image data-permission-id="desktop-notification" class="blocked-permission-icon desktop-notification-icon" role="button"
|
||||
data-l10n-id="urlbar-web-notifications-blocked"/>
|
||||
<image data-permission-id="camera" class="blocked-permission-icon camera-icon" role="button"
|
||||
|
@ -925,8 +922,6 @@
|
|||
data-l10n-id="urlbar-default-notification-anchor"/>
|
||||
<image id="geo-notification-icon" class="notification-anchor-icon geo-icon" role="button"
|
||||
data-l10n-id="urlbar-geolocation-notification-anchor"/>
|
||||
<image id="xr-notification-icon" class="notification-anchor-icon xr-icon" role="button"
|
||||
data-l10n-id="urlbar-xr-notification-anchor"/>
|
||||
<image id="autoplay-media-notification-icon" class="notification-anchor-icon autoplay-media-icon" role="button"
|
||||
data-l10n-id="urlbar-autoplay-notification-anchor"/>
|
||||
<image id="addons-notification-icon" class="notification-anchor-icon install-icon" role="button"
|
||||
|
|
|
@ -31,7 +31,7 @@ add_task(async function testTempPermissionRequestAfterExpiry() {
|
|||
let principal = Services.scriptSecurityManager.createContentPrincipalFromOrigin(
|
||||
ORIGIN
|
||||
);
|
||||
let ids = ["geo", "camera", "xr"];
|
||||
let ids = ["geo", "camera"];
|
||||
|
||||
for (let id of ids) {
|
||||
await BrowserTestUtils.withNewTab(PERMISSIONS_PAGE, async function(
|
||||
|
|
|
@ -41,7 +41,6 @@ window.onmessage = function(event) {
|
|||
<!-- This page could eventually request permissions from content
|
||||
and make sure that chrome responds appropriately -->
|
||||
<button id="geo" onclick="requestGeo()">Geolocation</button>
|
||||
<button id="xr" onclick="navigator.getVRDisplays()">XR</button>
|
||||
<button id="desktop-notification" onclick="Notification.requestPermission()">Notifications</button>
|
||||
<button id="push" onclick="requestPush()">Push Notifications</button>
|
||||
<button id="camera" onclick="navigator.mediaDevices.getUserMedia({video: true, fake: true})">Camera</button>
|
||||
|
|
|
@ -30,10 +30,7 @@ async function check(contentTask, options = {}) {
|
|||
let panel = await popupShownPromise;
|
||||
let notification = panel.children[0];
|
||||
let body = notification.querySelector(".popup-notification-body");
|
||||
if (
|
||||
notification.id == "geolocation-notification" ||
|
||||
notification.id == "xr-notification"
|
||||
) {
|
||||
if (notification.id == "geolocation-notification") {
|
||||
ok(
|
||||
body.innerHTML.includes("local file"),
|
||||
`file:// URIs should be displayed as local file.`
|
||||
|
@ -99,12 +96,6 @@ add_task(async function test_displayURI_geo() {
|
|||
});
|
||||
});
|
||||
|
||||
add_task(async function test_displayURI_xr() {
|
||||
await check(async function() {
|
||||
content.navigator.getVRDisplays();
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function test_displayURI_camera() {
|
||||
await check(async function() {
|
||||
content.navigator.mediaDevices.getUserMedia({ video: true, fake: true });
|
||||
|
@ -124,18 +115,6 @@ add_task(async function test_displayURI_geo_blob() {
|
|||
);
|
||||
});
|
||||
|
||||
add_task(async function test_displayURI_xr_blob() {
|
||||
await check(
|
||||
async function() {
|
||||
let text = "<script>navigator.getVRDisplays()</script>";
|
||||
let blob = new Blob([text], { type: "text/html" });
|
||||
let url = content.URL.createObjectURL(blob);
|
||||
content.location.href = url;
|
||||
},
|
||||
{ skipOnExtension: true }
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function test_displayURI_camera_blob() {
|
||||
await check(
|
||||
async function() {
|
||||
|
|
|
@ -4001,9 +4001,6 @@ const ContentPermissionIntegration = {
|
|||
case "geolocation": {
|
||||
return new PermissionUI.GeolocationPermissionPrompt(request);
|
||||
}
|
||||
case "xr": {
|
||||
return new PermissionUI.XRPermissionPrompt(request);
|
||||
}
|
||||
case "desktop-notification": {
|
||||
return new PermissionUI.DesktopNotificationPermissionPrompt(request);
|
||||
}
|
||||
|
|
|
@ -776,30 +776,6 @@
|
|||
" />
|
||||
</hbox>
|
||||
</hbox>
|
||||
|
||||
<hbox id="xrSettingsRow" align="center" role="group" aria-labelledby="xrPermissionsLabel">
|
||||
<description flex="1">
|
||||
<image class="xr-icon permission-icon" />
|
||||
<separator orient="vertical" class="thin"/>
|
||||
<label id="xrPermissionsLabel" data-l10n-id="permissions-xr"/>
|
||||
</description>
|
||||
<hbox pack="end">
|
||||
<button id="xrSettingsButton"
|
||||
is="highlightable-button"
|
||||
class="accessory-button"
|
||||
data-l10n-id="permissions-xr-settings"
|
||||
search-l10n-ids="
|
||||
permissions-remove.label,
|
||||
permissions-remove-all.label,
|
||||
permissions-button-cancel.label,
|
||||
permissions-button-ok.label,
|
||||
permissions-site-xr-window.title,
|
||||
permissions-site-xr-desc,
|
||||
permissions-site-xr-disable-label,
|
||||
permissions-site-xr-disable-desc,
|
||||
" />
|
||||
</hbox>
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
||||
<separator flex="1"/>
|
||||
|
|
|
@ -537,11 +537,6 @@ var gPrivacyPane = {
|
|||
"command",
|
||||
gPrivacyPane.showLocationExceptions
|
||||
);
|
||||
setEventListener(
|
||||
"xrSettingsButton",
|
||||
"command",
|
||||
gPrivacyPane.showXRExceptions
|
||||
);
|
||||
setEventListener(
|
||||
"cameraSettingsButton",
|
||||
"command",
|
||||
|
@ -1689,22 +1684,6 @@ var gPrivacyPane = {
|
|||
);
|
||||
},
|
||||
|
||||
// XR
|
||||
|
||||
/**
|
||||
* Displays the XR exceptions dialog where specific site XR
|
||||
* preferences can be set.
|
||||
*/
|
||||
showXRExceptions() {
|
||||
let params = { permissionType: "xr" };
|
||||
|
||||
gSubDialog.open(
|
||||
"chrome://browser/content/preferences/sitePermissions.xhtml",
|
||||
"resizable=yes",
|
||||
params
|
||||
);
|
||||
},
|
||||
|
||||
// CAMERA
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,12 +25,6 @@ const sitePermissionsL10n = {
|
|||
disableLabel: "permissions-site-location-disable-label",
|
||||
disableDescription: "permissions-site-location-disable-desc",
|
||||
},
|
||||
xr: {
|
||||
window: "permissions-site-xr-window",
|
||||
description: "permissions-site-xr-desc",
|
||||
disableLabel: "permissions-site-xr-disable-label",
|
||||
disableDescription: "permissions-site-xr-disable-desc",
|
||||
},
|
||||
camera: {
|
||||
window: "permissions-site-camera-window",
|
||||
description: "permissions-site-camera-desc",
|
||||
|
|
|
@ -3,7 +3,6 @@ tags = openwindow
|
|||
support-files =
|
||||
browser_privatebrowsing_concurrent_page.html
|
||||
browser_privatebrowsing_geoprompt_page.html
|
||||
browser_privatebrowsing_xrprompt_page.html
|
||||
browser_privatebrowsing_localStorage_before_after_page.html
|
||||
browser_privatebrowsing_localStorage_before_after_page2.html
|
||||
browser_privatebrowsing_localStorage_page1.html
|
||||
|
@ -36,6 +35,8 @@ skip-if = verify
|
|||
[browser_privatebrowsing_downloadLastDir_c.js]
|
||||
[browser_privatebrowsing_downloadLastDir_toggle.js]
|
||||
[browser_privatebrowsing_favicon.js]
|
||||
[browser_privatebrowsing_geoprompt.js]
|
||||
tags = geolocation
|
||||
[browser_privatebrowsing_lastpbcontextexited.js]
|
||||
[browser_privatebrowsing_localStorage.js]
|
||||
[browser_privatebrowsing_localStorage_before_after.js]
|
||||
|
@ -46,8 +47,6 @@ skip-if = verify
|
|||
[browser_privatebrowsing_placestitle.js]
|
||||
[browser_privatebrowsing_popupblocker.js]
|
||||
[browser_privatebrowsing_protocolhandler.js]
|
||||
[browser_privatebrowsing_rememberprompt.js]
|
||||
tags = geolocation xr
|
||||
[browser_privatebrowsing_sidebar.js]
|
||||
[browser_privatebrowsing_theming.js]
|
||||
[browser_privatebrowsing_ui.js]
|
||||
|
|
|
@ -14,29 +14,37 @@ add_task(async function setup() {
|
|||
});
|
||||
|
||||
add_task(async function test() {
|
||||
function checkPrompt(aURL, aName, aPrivateMode, aWindow) {
|
||||
const testPageURL =
|
||||
"https://example.com/browser/" +
|
||||
"browser/components/privatebrowsing/test/browser/browser_privatebrowsing_geoprompt_page.html";
|
||||
|
||||
function checkGeolocation(aPrivateMode, aWindow) {
|
||||
return (async function() {
|
||||
aWindow.gBrowser.selectedTab = BrowserTestUtils.addTab(
|
||||
aWindow.gBrowser,
|
||||
aURL
|
||||
testPageURL
|
||||
);
|
||||
await BrowserTestUtils.browserLoaded(aWindow.gBrowser.selectedBrowser);
|
||||
|
||||
let notification = aWindow.PopupNotifications.getNotification(aName);
|
||||
let notification = aWindow.PopupNotifications.getNotification(
|
||||
"geolocation"
|
||||
);
|
||||
|
||||
// Wait until the notification is available.
|
||||
while (!notification) {
|
||||
await new Promise(resolve => {
|
||||
executeSoon(resolve);
|
||||
});
|
||||
notification = aWindow.PopupNotifications.getNotification(aName);
|
||||
notification = aWindow.PopupNotifications.getNotification(
|
||||
"geolocation"
|
||||
);
|
||||
}
|
||||
|
||||
if (aPrivateMode) {
|
||||
// Make sure the notification is correctly displayed without a remember control
|
||||
ok(
|
||||
!notification.options.checkbox.show,
|
||||
"Secondary actions should not exist (always/never remember)"
|
||||
"Secondary actions should exist (always/never remember)"
|
||||
);
|
||||
} else {
|
||||
ok(
|
||||
|
@ -50,43 +58,23 @@ add_task(async function test() {
|
|||
})();
|
||||
}
|
||||
|
||||
function checkPrivateBrowsingRememberPrompt(aURL, aName) {
|
||||
return (async function() {
|
||||
let win = await BrowserTestUtils.openNewBrowserWindow();
|
||||
let browser = win.gBrowser.selectedBrowser;
|
||||
BrowserTestUtils.loadURI(browser, aURL);
|
||||
await BrowserTestUtils.browserLoaded(browser);
|
||||
let win = await BrowserTestUtils.openNewBrowserWindow();
|
||||
let browser = win.gBrowser.selectedBrowser;
|
||||
BrowserTestUtils.loadURI(browser, testPageURL);
|
||||
await BrowserTestUtils.browserLoaded(browser);
|
||||
|
||||
await checkPrompt(aURL, aName, false, win);
|
||||
await checkGeolocation(false, win);
|
||||
|
||||
let privateWin = await BrowserTestUtils.openNewBrowserWindow({
|
||||
private: true,
|
||||
});
|
||||
let privateBrowser = privateWin.gBrowser.selectedBrowser;
|
||||
BrowserTestUtils.loadURI(privateBrowser, aURL);
|
||||
await BrowserTestUtils.browserLoaded(privateBrowser);
|
||||
let privateWin = await BrowserTestUtils.openNewBrowserWindow({
|
||||
private: true,
|
||||
});
|
||||
let privateBrowser = privateWin.gBrowser.selectedBrowser;
|
||||
BrowserTestUtils.loadURI(privateBrowser, testPageURL);
|
||||
await BrowserTestUtils.browserLoaded(privateBrowser);
|
||||
|
||||
await checkPrompt(aURL, aName, true, privateWin);
|
||||
await checkGeolocation(true, privateWin);
|
||||
|
||||
// Cleanup
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
await BrowserTestUtils.closeWindow(privateWin);
|
||||
})();
|
||||
}
|
||||
|
||||
const geoTestPageURL =
|
||||
"https://example.com/browser/" +
|
||||
"browser/components/privatebrowsing/test/browser/browser_privatebrowsing_geoprompt_page.html";
|
||||
|
||||
await checkPrivateBrowsingRememberPrompt(geoTestPageURL, "geolocation");
|
||||
|
||||
const vrEnabled = Services.prefs.getBoolPref("dom.vr.enabled");
|
||||
|
||||
if (vrEnabled) {
|
||||
const xrTestPageURL =
|
||||
"https://example.com/browser/" +
|
||||
"browser/components/privatebrowsing/test/browser/browser_privatebrowsing_xrprompt_page.html";
|
||||
|
||||
await checkPrivateBrowsingRememberPrompt(xrTestPageURL, "xr");
|
||||
}
|
||||
// Cleanup
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
await BrowserTestUtils.closeWindow(privateWin);
|
||||
});
|
|
@ -1,11 +0,0 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>XR invoker</title>
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
navigator.getVRDisplays();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -57,8 +57,6 @@ urlbar-default-notification-anchor =
|
|||
.tooltiptext = Open message panel
|
||||
urlbar-geolocation-notification-anchor =
|
||||
.tooltiptext = Open location request panel
|
||||
urlbar-xr-notification-anchor =
|
||||
.tooltiptext = Open virtual reality permission panel
|
||||
urlbar-storage-access-anchor =
|
||||
.tooltiptext = Open browsing activity permission panel
|
||||
urlbar-translate-notification-anchor =
|
||||
|
@ -86,8 +84,6 @@ urlbar-tip-help-icon =
|
|||
|
||||
urlbar-geolocation-blocked =
|
||||
.tooltiptext = You have blocked location information for this website.
|
||||
urlbar-xr-blocked =
|
||||
.tooltiptext = You have blocked virtual reality device access for this website.
|
||||
urlbar-web-notifications-blocked =
|
||||
.tooltiptext = You have blocked notifications for this website.
|
||||
urlbar-camera-blocked =
|
||||
|
|
|
@ -139,16 +139,6 @@ permissions-site-location-disable-label =
|
|||
.label = Block new requests asking to access your location
|
||||
permissions-site-location-disable-desc = This will prevent any websites not listed above from requesting permission to access your location. Blocking access to your location may break some website features.
|
||||
|
||||
## Site Permissions - Virtual Reality
|
||||
|
||||
permissions-site-xr-window =
|
||||
.title = Settings - Virtual Reality Permissions
|
||||
.style = { permissions-window.style }
|
||||
permissions-site-xr-desc = The following websites have requested to access your virtual reality devices. You can specify which websites are allowed to access your virtual reality devices. You can also block new requests asking to access your virtual reality devices.
|
||||
permissions-site-xr-disable-label =
|
||||
.label = Block new requests asking to access your virtual reality devices
|
||||
permissions-site-xr-disable-desc = This will prevent any websites not listed above from requesting permission to access your virtual reality devices. Blocking access to your virtual reality devices may break some website features.
|
||||
|
||||
## Site Permissions - Camera
|
||||
|
||||
permissions-site-camera-window =
|
||||
|
|
|
@ -1113,11 +1113,6 @@ permissions-location-settings =
|
|||
.label = Settings…
|
||||
.accesskey = t
|
||||
|
||||
permissions-xr = Virtual Reality
|
||||
permissions-xr-settings =
|
||||
.label = Settings…
|
||||
.accesskey = t
|
||||
|
||||
permissions-camera = Camera
|
||||
permissions-camera-settings =
|
||||
.label = Settings…
|
||||
|
|
|
@ -628,15 +628,6 @@ geolocation.shareWithFile3=Will you allow this local file to access your locatio
|
|||
geolocation.shareWithSiteUnsafeDelegation=Will you allow %1$S to give %2$S permission to access your location?
|
||||
geolocation.remember=Remember this decision
|
||||
|
||||
# Virtual Reality Device UI
|
||||
xr.allow=Allow Virtual Reality Access
|
||||
xr.allow.accesskey=A
|
||||
xr.dontAllow=Don’t Allow
|
||||
xr.dontAllow.accesskey=n
|
||||
xr.shareWithSite3=Will you allow %S to access virtual reality devices? This may expose sensitive information.
|
||||
xr.shareWithFile3=Will you allow this local file to access virtual reality devices? This may expose sensitive information.
|
||||
xr.remember=Remember this decision
|
||||
|
||||
# Persistent storage UI
|
||||
persistentStorage.allow=Allow
|
||||
persistentStorage.allow.accesskey=A
|
||||
|
|
|
@ -40,7 +40,6 @@ permission.screen.label = Share the Screen
|
|||
permission.install.label = Install Add-ons
|
||||
permission.popup.label = Open Pop-up Windows
|
||||
permission.geo.label = Access Your Location
|
||||
permission.xr.label = Access Virtual Reality Devices
|
||||
permission.shortcuts.label = Override Keyboard Shortcuts
|
||||
permission.focus-tab-by-prompt.label = Switch to this Tab
|
||||
permission.persistent-storage.label = Store Data in Persistent Storage
|
||||
|
|
|
@ -833,111 +833,6 @@ GeolocationPermissionPrompt.prototype = {
|
|||
|
||||
PermissionUI.GeolocationPermissionPrompt = GeolocationPermissionPrompt;
|
||||
|
||||
/**
|
||||
* Creates a PermissionPrompt for a nsIContentPermissionRequest for
|
||||
* the WebXR API.
|
||||
*
|
||||
* @param request (nsIContentPermissionRequest)
|
||||
* The request for a permission from content.
|
||||
*/
|
||||
function XRPermissionPrompt(request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
XRPermissionPrompt.prototype = {
|
||||
__proto__: PermissionPromptForRequestPrototype,
|
||||
|
||||
get type() {
|
||||
return "xr";
|
||||
},
|
||||
|
||||
get permissionKey() {
|
||||
return "xr";
|
||||
},
|
||||
|
||||
get popupOptions() {
|
||||
let pref = "browser.xr.warning.infoURL";
|
||||
let options = {
|
||||
learnMoreURL: Services.urlFormatter.formatURLPref(pref),
|
||||
displayURI: false,
|
||||
name: this.getPrincipalName(),
|
||||
};
|
||||
|
||||
if (this.principal.URI.schemeIs("file")) {
|
||||
options.checkbox = { show: false };
|
||||
} else {
|
||||
// Don't offer "always remember" action in PB mode
|
||||
options.checkbox = {
|
||||
show: !PrivateBrowsingUtils.isWindowPrivate(this.browser.ownerGlobal),
|
||||
};
|
||||
}
|
||||
|
||||
if (options.checkbox.show) {
|
||||
options.checkbox.label = gBrowserBundle.GetStringFromName("xr.remember");
|
||||
}
|
||||
|
||||
return options;
|
||||
},
|
||||
|
||||
get notificationID() {
|
||||
return "xr";
|
||||
},
|
||||
|
||||
get anchorID() {
|
||||
return "xr-notification-icon";
|
||||
},
|
||||
|
||||
get message() {
|
||||
if (this.principal.URI.schemeIs("file")) {
|
||||
return gBrowserBundle.GetStringFromName("xr.shareWithFile3");
|
||||
}
|
||||
|
||||
return gBrowserBundle.formatStringFromName("xr.shareWithSite3", ["<>"]);
|
||||
},
|
||||
|
||||
get promptActions() {
|
||||
return [
|
||||
{
|
||||
label: gBrowserBundle.GetStringFromName("xr.allow"),
|
||||
accessKey: gBrowserBundle.GetStringFromName("xr.allow.accesskey"),
|
||||
action: SitePermissions.ALLOW,
|
||||
},
|
||||
{
|
||||
label: gBrowserBundle.GetStringFromName("xr.dontAllow"),
|
||||
accessKey: gBrowserBundle.GetStringFromName("xr.dontAllow.accesskey"),
|
||||
action: SitePermissions.BLOCK,
|
||||
},
|
||||
];
|
||||
},
|
||||
|
||||
_updateXRSharing(state) {
|
||||
let gBrowser = this.browser.ownerGlobal.gBrowser;
|
||||
if (gBrowser == null) {
|
||||
return;
|
||||
}
|
||||
gBrowser.updateBrowserSharing(this.browser, { xr: state });
|
||||
|
||||
let devicePermOrigins = this.browser.getDevicePermissionOrigins("xr");
|
||||
if (!state) {
|
||||
devicePermOrigins.delete(this.principal.origin);
|
||||
return;
|
||||
}
|
||||
devicePermOrigins.add(this.principal.origin);
|
||||
},
|
||||
|
||||
allow(...args) {
|
||||
this._updateXRSharing(true);
|
||||
PermissionPromptForRequestPrototype.allow.apply(this, args);
|
||||
},
|
||||
|
||||
cancel(...args) {
|
||||
this._updateXRSharing(false);
|
||||
PermissionPromptForRequestPrototype.cancel.apply(this, args);
|
||||
},
|
||||
};
|
||||
|
||||
PermissionUI.XRPermissionPrompt = XRPermissionPrompt;
|
||||
|
||||
/**
|
||||
* Creates a PermissionPrompt for a nsIContentPermissionRequest for
|
||||
* the Desktop Notification API.
|
||||
|
|
|
@ -966,10 +966,6 @@ var gPermissionObject = {
|
|||
exactHostMatch: true,
|
||||
},
|
||||
|
||||
xr: {
|
||||
exactHostMatch: true,
|
||||
},
|
||||
|
||||
"focus-tab-by-prompt": {
|
||||
exactHostMatch: true,
|
||||
states: [SitePermissions.UNKNOWN, SitePermissions.ALLOW],
|
||||
|
|
|
@ -18,11 +18,6 @@ add_task(async function test_geo_permission_prompt() {
|
|||
await testPrompt(PermissionUI.GeolocationPermissionPrompt);
|
||||
});
|
||||
|
||||
// Tests that XRPermissionPrompt works as expected
|
||||
add_task(async function test_xr_permission_prompt() {
|
||||
await testPrompt(PermissionUI.XRPermissionPrompt);
|
||||
});
|
||||
|
||||
// Tests that DesktopNotificationPermissionPrompt works as expected
|
||||
add_task(async function test_desktop_notification_permission_prompt() {
|
||||
Services.prefs.setBoolPref(
|
||||
|
|
|
@ -59,8 +59,6 @@ add_task(async function testGetAllPermissionDetailsForBrowser() {
|
|||
SitePermissions.ALLOW
|
||||
);
|
||||
|
||||
SitePermissions.setForPrincipal(principal, "xr", SitePermissions.ALLOW);
|
||||
|
||||
let permissions = SitePermissions.getAllPermissionDetailsForBrowser(
|
||||
tab.linkedBrowser
|
||||
);
|
||||
|
@ -114,21 +112,11 @@ add_task(async function testGetAllPermissionDetailsForBrowser() {
|
|||
scope: SitePermissions.SCOPE_PERSISTENT,
|
||||
});
|
||||
|
||||
let xr = permissions.find(({ id }) => id === "xr");
|
||||
Assert.deepEqual(xr, {
|
||||
id: "xr",
|
||||
label: "Access Virtual Reality Devices",
|
||||
state: SitePermissions.ALLOW,
|
||||
scope: SitePermissions.SCOPE_PERSISTENT,
|
||||
});
|
||||
|
||||
SitePermissions.removeFromPrincipal(principal, "cookie");
|
||||
SitePermissions.removeFromPrincipal(principal, "popup");
|
||||
SitePermissions.removeFromPrincipal(principal, "geo");
|
||||
SitePermissions.removeFromPrincipal(principal, "shortcuts");
|
||||
|
||||
SitePermissions.removeFromPrincipal(principal, "xr");
|
||||
|
||||
Services.prefs.clearUserPref("permissions.default.shortcuts");
|
||||
|
||||
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
|
|
|
@ -28,7 +28,6 @@ add_task(async function testPermissionsListing() {
|
|||
"shortcuts",
|
||||
"persistent-storage",
|
||||
"storage-access",
|
||||
"xr",
|
||||
];
|
||||
if (RESIST_FINGERPRINTING_ENABLED) {
|
||||
// Canvas permission should be hidden unless privacy.resistFingerprinting
|
||||
|
@ -185,7 +184,6 @@ add_task(async function testExactHostMatch() {
|
|||
"microphone",
|
||||
"screen",
|
||||
"geo",
|
||||
"xr",
|
||||
"persistent-storage",
|
||||
];
|
||||
if (RESIST_FINGERPRINTING_ENABLED) {
|
||||
|
|
|
@ -69,10 +69,6 @@
|
|||
list-style-image: url(chrome://browser/skin/notification-icons/geo.svg);
|
||||
}
|
||||
|
||||
.xr-icon {
|
||||
list-style-image: url(chrome://browser/skin/notification-icons/xr.svg);
|
||||
}
|
||||
|
||||
.camera-icon {
|
||||
list-style-image: url(chrome://browser/skin/notification-icons/camera.svg);
|
||||
}
|
||||
|
|
|
@ -91,8 +91,6 @@
|
|||
skin/classic/browser/notification-icons/popup-subitem.svg (../shared/notification-icons/popup-subitem.svg)
|
||||
skin/classic/browser/notification-icons/screen-blocked.svg (../shared/notification-icons/screen-blocked.svg)
|
||||
skin/classic/browser/notification-icons/screen.svg (../shared/notification-icons/screen.svg)
|
||||
skin/classic/browser/notification-icons/xr-blocked.svg (../shared/notification-icons/xr-blocked.svg)
|
||||
skin/classic/browser/notification-icons/xr.svg (../shared/notification-icons/xr.svg)
|
||||
skin/classic/browser/notification-icons/update.svg (../shared/notification-icons/update.svg)
|
||||
skin/classic/browser/notification-icons/midi.svg (../shared/notification-icons/midi.svg)
|
||||
skin/classic/browser/notification-icons/webauthn.svg (../shared/notification-icons/webauthn.svg)
|
||||
|
|
|
@ -70,18 +70,6 @@
|
|||
list-style-image: url(chrome://browser/skin/notification-icons/geo-detailed.svg);
|
||||
}
|
||||
|
||||
.xr-icon {
|
||||
list-style-image: url(chrome://browser/skin/notification-icons/xr.svg);
|
||||
}
|
||||
|
||||
.xr-icon.blocked-permission-icon {
|
||||
list-style-image: url(chrome://browser/skin/notification-icons/xr-blocked.svg);
|
||||
}
|
||||
|
||||
.popup-notification-icon[popupid="xr"] {
|
||||
list-style-image: url(chrome://browser/skin/notification-icons/xr.svg);
|
||||
}
|
||||
|
||||
.autoplay-media-icon {
|
||||
list-style-image: url(chrome://browser/skin/notification-icons/autoplay-media.svg);
|
||||
}
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
<!-- 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/. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="context-fill" fill-opacity="context-fill-opacity">
|
||||
<path d="M14.3,4.3l-2.6,2.6c0.6,0.3,0.9,1,0.6,1.6c-0.3,0.6-1,0.9-1.6,0.6c-0.2-0.1-0.4-0.3-0.6-0.6l-1.7,1.7L9,11.5
|
||||
c0.1,0.1,0.2,0.2,0.3,0.2h4.8c0.6,0,1-0.5,1-1V5.3C15.1,4.8,14.8,4.4,14.3,4.3z"/>
|
||||
<path d="M12.8,4.4c0.3-0.3,0.2-0.7,0-0.9c-0.3-0.2-0.7-0.2-0.9,0l-0.8,0.8H2c-0.6,0-1,0.5-1,1v5.4c0,0.6,0.5,1,1,1h1.7
|
||||
c-0.2,0.3,0,0.7,0.3,0.9c0.3,0.1,0.6,0.1,0.8-0.1L12.8,4.4z M3.7,8.5c-0.3-0.6,0-1.3,0.6-1.6c0.6-0.3,1.3,0,1.6,0.6s0,1.3-0.6,1.6
|
||||
C5.1,9.2,5,9.2,4.8,9.2C4.3,9.2,3.9,8.9,3.7,8.5z"/>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 841 B |
|
@ -1,9 +0,0 @@
|
|||
<!-- 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/. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="context-fill" fill-opacity="context-fill-opacity">
|
||||
<path d="M14.1,4.3H2c-0.6,0-1,0.5-1,1v5.4c0,0.6,0.5,1,1,1h4.7c0.1,0,0.2-0.1,0.3-0.2l0.7-1.4C7.8,9.9,8,9.9,8.1,9.9
|
||||
c0.1,0,0.1,0.1,0.2,0.2L9,11.5c0.1,0.1,0.2,0.2,0.3,0.2h4.8c0.6,0,1-0.5,1-1V5.3C15.1,4.7,14.6,4.3,14.1,4.3z M4.8,9.2
|
||||
C4.1,9.2,3.6,8.7,3.6,8c0-0.7,0.5-1.2,1.2-1.2C5.5,6.8,6,7.3,6,8c0,0,0,0,0,0C6,8.7,5.5,9.2,4.8,9.2z M11.2,9.2
|
||||
C10.5,9.2,10,8.7,10,8c0-0.7,0.5-1.2,1.2-1.2c0.7,0,1.2,0.5,1.2,1.2c0,0,0,0,0,0C12.4,8.7,11.9,9.2,11.2,9.2z"/>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 798 B |
|
@ -10,7 +10,6 @@
|
|||
</head>
|
||||
<body>
|
||||
<button id="geo" onclick="navigator.geolocation.getCurrentPosition(() => {})">Geolocation</button>
|
||||
<button id="xr" onclick="content.navigator.getVRDisplays();">WebXR</button>
|
||||
<button id="persistent-storage" onclick="navigator.storage.persist()">Persistent Storage</button>
|
||||
<button id="webRTC-shareDevices" onclick="shareDevice({video: true, fake: true});">Video</button>
|
||||
<button id="webRTC-shareMicrophone" onclick="shareDevice({audio: true, fake: true});">Audio</button>
|
||||
|
|
|
@ -1480,6 +1480,9 @@ already_AddRefed<Promise> Navigator::GetVRDisplays(ErrorResult& aRv) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
nsGlobalWindowInner* win = nsGlobalWindowInner::Cast(mWindow);
|
||||
win->NotifyVREventListenerAdded();
|
||||
|
||||
RefPtr<Promise> p = Promise::Create(mWindow->AsGlobal(), aRv);
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
|
@ -1507,53 +1510,39 @@ already_AddRefed<Promise> Navigator::GetVRDisplays(ErrorResult& aRv) {
|
|||
}
|
||||
|
||||
void Navigator::FinishGetVRDisplays(bool isWebVRSupportedInwindow, Promise* p) {
|
||||
if (!isWebVRSupportedInwindow) {
|
||||
if (isWebVRSupportedInwindow) {
|
||||
nsGlobalWindowInner* win = nsGlobalWindowInner::Cast(mWindow);
|
||||
|
||||
// Since FinishGetVRDisplays can be called asynchronously after an IPC
|
||||
// response, it's possible that the Window can be torn down before this
|
||||
// call. In that case, the Window's cyclic references to VR objects are
|
||||
// also torn down and should not be recreated via
|
||||
// NotifyVREventListenerAdded.
|
||||
if (!win->IsDying()) {
|
||||
win->NotifyVREventListenerAdded();
|
||||
// We pass mWindow's id to RefreshVRDisplays, so
|
||||
// NotifyVRDisplaysUpdated will be called asynchronously, resolving
|
||||
// the promises in mVRGetDisplaysPromises.
|
||||
if (!VRDisplay::RefreshVRDisplays(win->WindowID())) {
|
||||
// Failed to refresh, reject the promise now
|
||||
p->MaybeRejectWithTypeError(u"Failed to find attached VR displays.");
|
||||
} else {
|
||||
// Succeeded, so cache the promise to resolve later
|
||||
mVRGetDisplaysPromises.AppendElement(p);
|
||||
}
|
||||
} else {
|
||||
// The Window has been torn down, so there is no further work that can
|
||||
// be done.
|
||||
p->MaybeRejectWithTypeError(
|
||||
u"Unable to return VRDisplays for a closed window.");
|
||||
}
|
||||
} else {
|
||||
// WebVR in this window is not supported, so resolve the promise
|
||||
// with no displays available
|
||||
nsTArray<RefPtr<VRDisplay>> vrDisplaysEmpty;
|
||||
p->MaybeResolve(vrDisplaysEmpty);
|
||||
return;
|
||||
}
|
||||
|
||||
// Since FinishGetVRDisplays can be called asynchronously after an IPC
|
||||
// response, it's possible that the Window can be torn down before this
|
||||
// call. In that case, the Window's cyclic references to VR objects are
|
||||
// also torn down and should not be recreated via
|
||||
// NotifyVREventListenerAdded.
|
||||
nsGlobalWindowInner* win = nsGlobalWindowInner::Cast(mWindow);
|
||||
if (win->IsDying()) {
|
||||
// The Window has been torn down, so there is no further work that can
|
||||
// be done.
|
||||
p->MaybeRejectWithTypeError(
|
||||
u"Unable to return VRDisplays for a closed window.");
|
||||
return;
|
||||
}
|
||||
|
||||
mVRGetDisplaysPromises.AppendElement(p);
|
||||
win->RequestXRPermission();
|
||||
}
|
||||
|
||||
void Navigator::OnXRPermissionRequestAllow() {
|
||||
nsGlobalWindowInner* win = nsGlobalWindowInner::Cast(mWindow);
|
||||
|
||||
// We pass mWindow's id to RefreshVRDisplays, so NotifyVRDisplaysUpdated will
|
||||
// be called asynchronously, resolving the promises in mVRGetDisplaysPromises.
|
||||
if (!VRDisplay::RefreshVRDisplays(win->WindowID())) {
|
||||
for (auto& p : mVRGetDisplaysPromises) {
|
||||
// Failed to refresh, reject the promise now
|
||||
p->MaybeRejectWithTypeError(u"Failed to find attached VR displays.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Navigator::OnXRPermissionRequestCancel() {
|
||||
nsTArray<RefPtr<VRDisplay>> vrDisplays;
|
||||
for (auto& p : mVRGetDisplaysPromises) {
|
||||
// Resolve the promise with no vr displays when
|
||||
// the user blocks access.
|
||||
p->MaybeResolve(vrDisplays);
|
||||
}
|
||||
mVRGetDisplaysPromises.Clear();
|
||||
}
|
||||
|
||||
void Navigator::GetActiveVRDisplays(
|
||||
|
|
|
@ -181,8 +181,6 @@ class Navigator final : public nsISupports, public nsWrapperCache {
|
|||
already_AddRefed<Promise> GetVRDisplays(ErrorResult& aRv);
|
||||
void FinishGetVRDisplays(bool isWebVRSupportedInwindow, Promise* p);
|
||||
void GetActiveVRDisplays(nsTArray<RefPtr<VRDisplay>>& aDisplays) const;
|
||||
void OnXRPermissionRequestAllow();
|
||||
void OnXRPermissionRequestCancel();
|
||||
VRServiceTest* RequestVRServiceTest();
|
||||
bool IsWebVRContentDetected() const;
|
||||
bool IsWebVRContentPresenting() const;
|
||||
|
|
|
@ -187,7 +187,6 @@
|
|||
#include "mozilla/dom/VRDisplayEvent.h"
|
||||
#include "mozilla/dom/VRDisplayEventBinding.h"
|
||||
#include "mozilla/dom/VREventObserver.h"
|
||||
#include "mozilla/dom/XRPermissionRequest.h"
|
||||
|
||||
#include "nsRefreshDriver.h"
|
||||
#include "Layers.h"
|
||||
|
@ -840,8 +839,6 @@ nsGlobalWindowInner::nsGlobalWindowInner(nsGlobalWindowOuter* aOuterWindow,
|
|||
mHasGamepad(false),
|
||||
mHasVREvents(false),
|
||||
mHasVRDisplayActivateEvents(false),
|
||||
mXRPermissionRequestInFlight(false),
|
||||
mXRPermissionGranted(false),
|
||||
mHasSeenGamepadInput(false),
|
||||
mSuspendDepth(0),
|
||||
mFreezeDepth(0),
|
||||
|
@ -1142,8 +1139,6 @@ void nsGlobalWindowInner::FreeInnerObjects() {
|
|||
DisableVRUpdates();
|
||||
mHasVREvents = false;
|
||||
mHasVRDisplayActivateEvents = false;
|
||||
mXRPermissionRequestInFlight = false;
|
||||
mXRPermissionGranted = false;
|
||||
mVRDisplays.Clear();
|
||||
|
||||
// This breaks a cycle between the window and the ClientSource object.
|
||||
|
@ -6019,48 +6014,13 @@ void nsGlobalWindowInner::SetHasGamepadEventListener(
|
|||
}
|
||||
}
|
||||
|
||||
void nsGlobalWindowInner::RequestXRPermission() {
|
||||
if (mXRPermissionGranted) {
|
||||
// Don't prompt redundantly once permission to
|
||||
// access XR devices has been granted.
|
||||
OnXRPermissionRequestAllow();
|
||||
return;
|
||||
}
|
||||
if (mXRPermissionRequestInFlight) {
|
||||
// Don't allow multiple simultaneous permissions requests;
|
||||
return;
|
||||
}
|
||||
mXRPermissionRequestInFlight = true;
|
||||
RefPtr<XRPermissionRequest> request =
|
||||
new XRPermissionRequest(this, WindowID());
|
||||
Unused << NS_WARN_IF(NS_FAILED(request->Start()));
|
||||
}
|
||||
|
||||
void nsGlobalWindowInner::OnXRPermissionRequestAllow() {
|
||||
mXRPermissionRequestInFlight = false;
|
||||
mXRPermissionGranted = true;
|
||||
|
||||
NotifyVREventListenerAdded();
|
||||
|
||||
dom::Navigator* nav = Navigator();
|
||||
MOZ_ASSERT(nav != nullptr);
|
||||
nav->OnXRPermissionRequestAllow();
|
||||
}
|
||||
|
||||
void nsGlobalWindowInner::OnXRPermissionRequestCancel() {
|
||||
mXRPermissionRequestInFlight = false;
|
||||
dom::Navigator* nav = Navigator();
|
||||
MOZ_ASSERT(nav != nullptr);
|
||||
nav->OnXRPermissionRequestCancel();
|
||||
}
|
||||
|
||||
void nsGlobalWindowInner::EventListenerAdded(nsAtom* aType) {
|
||||
if (aType == nsGkAtoms::onvrdisplayactivate ||
|
||||
aType == nsGkAtoms::onvrdisplayconnect ||
|
||||
aType == nsGkAtoms::onvrdisplaydeactivate ||
|
||||
aType == nsGkAtoms::onvrdisplaydisconnect ||
|
||||
aType == nsGkAtoms::onvrdisplaypresentchange) {
|
||||
RequestXRPermission();
|
||||
NotifyVREventListenerAdded();
|
||||
}
|
||||
|
||||
if (aType == nsGkAtoms::onvrdisplayactivate) {
|
||||
|
|
|
@ -371,9 +371,6 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
|
|||
bool HasUsedVR() const;
|
||||
bool IsVRContentDetected() const;
|
||||
bool IsVRContentPresenting() const;
|
||||
void RequestXRPermission();
|
||||
void OnXRPermissionRequestAllow();
|
||||
void OnXRPermissionRequestCancel();
|
||||
|
||||
using EventTarget::EventListenerAdded;
|
||||
virtual void EventListenerAdded(nsAtom* aType) override;
|
||||
|
@ -1288,15 +1285,6 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
|
|||
|
||||
// Indicates whether this window wants VRDisplayActivate events
|
||||
bool mHasVRDisplayActivateEvents : 1;
|
||||
|
||||
// Indicates that an XR permission request has been requested
|
||||
// but has not yet been resolved.
|
||||
bool mXRPermissionRequestInFlight : 1;
|
||||
|
||||
// Indicates that an XR permission request has been granted.
|
||||
// The page should not request permission multiple times.
|
||||
bool mXRPermissionGranted : 1;
|
||||
|
||||
nsCheapSet<nsUint32HashKey> mGamepadIndexSet;
|
||||
nsRefPtrHashtable<nsUint32HashKey, mozilla::dom::Gamepad> mGamepads;
|
||||
bool mHasSeenGamepadInput;
|
||||
|
|
|
@ -1296,37 +1296,43 @@ var interfaceNamesInGlobalScope = [
|
|||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{ name: "VisualViewport", insecureContext: true },
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{ name: "VRDisplay", releaseNonWindowsAndMac: false },
|
||||
{ name: "VRDisplay", insecureContext: true, releaseNonWindowsAndMac: false },
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{
|
||||
name: "VRDisplayCapabilities",
|
||||
insecureContext: true,
|
||||
releaseNonWindowsAndMac: false,
|
||||
},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{
|
||||
name: "VRDisplayEvent",
|
||||
insecureContext: true,
|
||||
releaseNonWindowsAndMac: false,
|
||||
},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{
|
||||
name: "VREyeParameters",
|
||||
insecureContext: true,
|
||||
releaseNonWindowsAndMac: false,
|
||||
},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{
|
||||
name: "VRFieldOfView",
|
||||
insecureContext: true,
|
||||
releaseNonWindowsAndMac: false,
|
||||
},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{
|
||||
name: "VRFrameData",
|
||||
insecureContext: true,
|
||||
releaseNonWindowsAndMac: false,
|
||||
},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{ name: "VRPose", releaseNonWindowsAndMac: false },
|
||||
{ name: "VRPose", insecureContext: true, releaseNonWindowsAndMac: false },
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{
|
||||
name: "VRStageParameters",
|
||||
insecureContext: true,
|
||||
releaseNonWindowsAndMac: false,
|
||||
},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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 "XRPermissionRequest.h"
|
||||
#include "nsIGlobalObject.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
//-------------------------------------------------
|
||||
// XR Permission Requests
|
||||
//-------------------------------------------------
|
||||
|
||||
NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(XRPermissionRequest,
|
||||
ContentPermissionRequestBase)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(XRPermissionRequest,
|
||||
ContentPermissionRequestBase)
|
||||
|
||||
XRPermissionRequest::XRPermissionRequest(nsPIDOMWindowInner* aWindow,
|
||||
uint64_t aWindowId)
|
||||
: ContentPermissionRequestBase(aWindow->GetDoc()->NodePrincipal(), aWindow,
|
||||
NS_LITERAL_CSTRING("dom.vr"),
|
||||
NS_LITERAL_CSTRING("xr")),
|
||||
mWindowId(aWindowId) {
|
||||
MOZ_ASSERT(aWindow);
|
||||
MOZ_ASSERT(aWindow->GetDoc());
|
||||
mPrincipal = aWindow->GetDoc()->NodePrincipal();
|
||||
MOZ_ASSERT(mPrincipal);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
XRPermissionRequest::Cancel() {
|
||||
nsGlobalWindowInner* window =
|
||||
nsGlobalWindowInner::GetInnerWindowWithId(mWindowId);
|
||||
if (!window) {
|
||||
return NS_OK;
|
||||
}
|
||||
window->OnXRPermissionRequestCancel();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
XRPermissionRequest::Allow(JS::HandleValue aChoices) {
|
||||
MOZ_ASSERT(aChoices.isUndefined());
|
||||
nsGlobalWindowInner* window =
|
||||
nsGlobalWindowInner::GetInnerWindowWithId(mWindowId);
|
||||
if (!window) {
|
||||
return NS_OK;
|
||||
}
|
||||
window->OnXRPermissionRequestAllow();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult XRPermissionRequest::Start() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
PromptResult pr = CheckPromptPrefs();
|
||||
if (pr == PromptResult::Granted) {
|
||||
return Allow(JS::UndefinedHandleValue);
|
||||
}
|
||||
if (pr == PromptResult::Denied) {
|
||||
return Cancel();
|
||||
}
|
||||
|
||||
return nsContentPermissionUtils::AskPermission(this, mWindow);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -1,41 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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_XRPermissionRequest_h_
|
||||
#define mozilla_dom_XRPermissionRequest_h_
|
||||
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "nsContentPermissionHelper.h"
|
||||
#include "nsISupports.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
/**
|
||||
* Handles permission dialog management when requesting XR device access.
|
||||
*/
|
||||
class XRPermissionRequest final : public ContentPermissionRequestBase {
|
||||
public:
|
||||
XRPermissionRequest(nsPIDOMWindowInner* aWindow, uint64_t aWindowId);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(XRPermissionRequest,
|
||||
ContentPermissionRequestBase)
|
||||
// nsIContentPermissionRequest
|
||||
NS_IMETHOD Cancel(void) override;
|
||||
NS_IMETHOD Allow(JS::HandleValue choices) override;
|
||||
nsresult Start();
|
||||
|
||||
private:
|
||||
~XRPermissionRequest() = default;
|
||||
|
||||
uint64_t mWindowId;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_XR_h_
|
|
@ -11,16 +11,14 @@ EXPORTS.mozilla.dom += [
|
|||
'VRDisplay.h',
|
||||
'VRDisplayEvent.h',
|
||||
'VREventObserver.h',
|
||||
'VRServiceTest.h',
|
||||
'XRPermissionRequest.h',
|
||||
'VRServiceTest.h'
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES = [
|
||||
'VRDisplay.cpp',
|
||||
'VRDisplayEvent.cpp',
|
||||
'VREventObserver.cpp',
|
||||
'VRServiceTest.cpp',
|
||||
'XRPermissionRequest.cpp',
|
||||
'VRServiceTest.cpp'
|
||||
]
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
|
|
@ -213,12 +213,11 @@ partial interface Navigator {
|
|||
GamepadServiceTest requestGamepadServiceTest();
|
||||
};
|
||||
|
||||
// https://immersive-web.github.io/webvr/spec/1.1/#interface-navigator
|
||||
partial interface Navigator {
|
||||
[Throws, SecureContext, Pref="dom.vr.enabled"]
|
||||
[Throws, Pref="dom.vr.enabled"]
|
||||
Promise<sequence<VRDisplay>> getVRDisplays();
|
||||
// TODO: Use FrozenArray once available. (Bug 1236777)
|
||||
[SecureContext, Frozen, Cached, Pure, Pref="dom.vr.enabled"]
|
||||
[Frozen, Cached, Pure, Pref="dom.vr.enabled"]
|
||||
readonly attribute sequence<VRDisplay> activeVRDisplays;
|
||||
[ChromeOnly, Pref="dom.vr.enabled"]
|
||||
readonly attribute boolean isWebVRContentDetected;
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
/* -*- 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://immersive-web.github.io/webvr/spec/1.1/
|
||||
*/
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
enum VREye {
|
||||
"left",
|
||||
|
@ -14,7 +10,6 @@ enum VREye {
|
|||
|
||||
[Pref="dom.vr.enabled",
|
||||
HeaderFile="mozilla/dom/VRDisplay.h",
|
||||
SecureContext,
|
||||
Exposed=Window]
|
||||
interface VRFieldOfView {
|
||||
readonly attribute double upDegrees;
|
||||
|
@ -56,7 +51,6 @@ dictionary VRLayer {
|
|||
*/
|
||||
[Pref="dom.vr.enabled",
|
||||
HeaderFile="mozilla/dom/VRDisplay.h",
|
||||
SecureContext,
|
||||
Exposed=Window]
|
||||
interface VRDisplayCapabilities {
|
||||
/**
|
||||
|
@ -99,7 +93,6 @@ interface VRDisplayCapabilities {
|
|||
*/
|
||||
[Pref="dom.vr.enabled",
|
||||
HeaderFile="mozilla/dom/VRDisplay.h",
|
||||
SecureContext,
|
||||
Exposed=Window]
|
||||
interface VRStageParameters {
|
||||
/**
|
||||
|
@ -126,7 +119,6 @@ interface VRStageParameters {
|
|||
|
||||
[Pref="dom.vr.enabled",
|
||||
HeaderFile="mozilla/dom/VRDisplay.h",
|
||||
SecureContext,
|
||||
Exposed=Window]
|
||||
interface VRPose
|
||||
{
|
||||
|
@ -148,7 +140,6 @@ interface VRPose
|
|||
|
||||
[Pref="dom.vr.enabled",
|
||||
HeaderFile="mozilla/dom/VRDisplay.h",
|
||||
SecureContext,
|
||||
Exposed=Window]
|
||||
interface VRFrameData {
|
||||
constructor();
|
||||
|
@ -166,7 +157,6 @@ interface VRFrameData {
|
|||
|
||||
[Pref="dom.vr.enabled",
|
||||
HeaderFile="mozilla/dom/VRDisplay.h",
|
||||
SecureContext,
|
||||
Exposed=Window]
|
||||
interface VREyeParameters {
|
||||
/**
|
||||
|
@ -191,7 +181,6 @@ interface VREyeParameters {
|
|||
|
||||
[Pref="dom.vr.enabled",
|
||||
HeaderFile="mozilla/dom/VRDisplay.h",
|
||||
SecureContext,
|
||||
Exposed=Window]
|
||||
interface VRDisplay : EventTarget {
|
||||
/**
|
||||
|
|
|
@ -38,7 +38,6 @@ static const DelegateInfo sPermissionsMap[] = {
|
|||
{"camera", u"camera", DelegatePolicy::eDelegateUseFeaturePolicy},
|
||||
{"microphone", u"microphone", DelegatePolicy::eDelegateUseFeaturePolicy},
|
||||
{"screen", u"display-capture", DelegatePolicy::eDelegateUseFeaturePolicy},
|
||||
{"xr", nullptr, DelegatePolicy::ePersistDeniedCrossOrigin},
|
||||
};
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION(PermissionDelegateHandler)
|
||||
|
|
|
@ -113,9 +113,9 @@ public class GeckoViewActivity extends AppCompatActivity {
|
|||
|
||||
### Content Permissions
|
||||
|
||||
Content permissions are requested whenever a site wants access to content that is stored on the device. The content permissions that can be requested through GeckoView are; [`Geolocation`][10], [`Site Notifications`][11] [`Persistent Storage`][12] and [`XR`][13] access.
|
||||
Content permissions are requested whenever a site wants access to content that is stored on the device. The content permissions that can be requested through GeckoView are; [`Geolocation`][10], [`Site Notifications`][11] and [`Persistent Storage`][12] access.
|
||||
|
||||
When you receive an [`onContentPermissionRequest`][14] call, you will also receive the `GeckoSession` the request was sent from, the URI of the site that requested the permission, as a String, the type of the content permission requested (geolocation, site notification or persistent storage), and a [`Callback`][4] to respond to the request. It is then up to the app to present UI to the user asking for the permissions, and to notify GeckoView of the response via the `Callback`.
|
||||
When you receive an [`onContentPermissionRequest`][13] call, you will also receive the `GeckoSession` the request was sent from, the URI of the site that requested the permission, as a String, the type of the content permission requested (geolocation, site notification or persistent storage), and a [`Callback`][4] to respond to the request. It is then up to the app to present UI to the user asking for the permissions, and to notify GeckoView of the response via the `Callback`.
|
||||
|
||||
*Please note, in the case of `PERMISSION_DESKTOP_NOTIFICATION` and `PERMISSION_PERSISTENT_STORAGE`, GeckoView does not track accepted permissions and prevent further requests being sent for a particular site. It is therefore up to the calling app to do this if that is the desired behaviour. The code below demonstrates how to track storage permissions by site and track notification permission rejection for the whole app*
|
||||
|
||||
|
@ -145,8 +145,6 @@ private class ExamplePermissionDelegate implements GeckoSession.PermissionDelega
|
|||
return;
|
||||
}
|
||||
resId = R.string.request_storage;
|
||||
} else if (PERMISSION_XR == type) {
|
||||
resId = R.string.request_xr;
|
||||
} else { // unknown permission type
|
||||
callback.reject();
|
||||
return;
|
||||
|
@ -185,7 +183,7 @@ private class ExamplePermissionDelegate implements GeckoSession.PermissionDelega
|
|||
### Media Permissions
|
||||
Media permissions are requested whenever a site wants access to play or record media from the device's camera and microphone.
|
||||
|
||||
When you receive an [`onMediaPermissionRequest`][15] call, you will also receive the `GeckoSession` the request was sent from, the URI of the site that requested the permission, as a String, the list of video devices available, if requesting video, the list of audio devices available, if requesting audio, and a [`MediaCallback`][17] to respond to the request.
|
||||
When you receive an [`onMediaPermissionRequest`][14] call, you will also receive the `GeckoSession` the request was sent from, the URI of the site that requested the permission, as a String, the list of video devices available, if requesting video, the list of audio devices available, if requesting audio, and a [`MediaCallback`][15] to respond to the request.
|
||||
|
||||
It is up to the app to present UI to the user asking for the permissions, and to notify GeckoView of the response via the `MediaCallback`.
|
||||
|
||||
|
@ -282,8 +280,7 @@ To see the `PermissionsDelegate` in action, you can find the full example implem
|
|||
[10]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_GEOLOCATION
|
||||
[11]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_DESKTOP_NOTIFICATION
|
||||
[12]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_PERSISTENT_STORAGE
|
||||
[13]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_XR
|
||||
[14]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#onContentPermissionRequest-org.mozilla.geckoview.GeckoSession-java.lang.String-int-org.mozilla.geckoview.GeckoSession.PermissionDelegate.Callback-
|
||||
[15]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#onMediaPermissionRequest-org.mozilla.geckoview.GeckoSession-java.lang.String-org.mozilla.geckoview.GeckoSession.PermissionDelegate.MediaSource:A-org.mozilla.geckoview.GeckoSession.PermissionDelegate.MediaSource:A-org.mozilla.geckoview.GeckoSession.PermissionDelegate.MediaCallback-
|
||||
[16]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.MediaCallback.html
|
||||
[17]: https://searchfox.org/mozilla-central/source/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java#686
|
||||
[13]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#onContentPermissionRequest-org.mozilla.geckoview.GeckoSession-java.lang.String-int-org.mozilla.geckoview.GeckoSession.PermissionDelegate.Callback-
|
||||
[14]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#onMediaPermissionRequest-org.mozilla.geckoview.GeckoSession-java.lang.String-org.mozilla.geckoview.GeckoSession.PermissionDelegate.MediaSource:A-org.mozilla.geckoview.GeckoSession.PermissionDelegate.MediaSource:A-org.mozilla.geckoview.GeckoSession.PermissionDelegate.MediaCallback-
|
||||
[15]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.MediaCallback.html
|
||||
[16]: https://searchfox.org/mozilla-central/source/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java#686
|
||||
|
|
|
@ -777,7 +777,6 @@ package org.mozilla.geckoview {
|
|||
field public static final int PERMISSION_DESKTOP_NOTIFICATION = 1;
|
||||
field public static final int PERMISSION_GEOLOCATION = 0;
|
||||
field public static final int PERMISSION_PERSISTENT_STORAGE = 2;
|
||||
field public static final int PERMISSION_XR = 3;
|
||||
}
|
||||
|
||||
public static interface GeckoSession.PermissionDelegate.Callback {
|
||||
|
|
|
@ -792,8 +792,6 @@ public class GeckoSession implements Parcelable {
|
|||
type = PermissionDelegate.PERMISSION_DESKTOP_NOTIFICATION;
|
||||
} else if ("persistent-storage".equals(typeString)) {
|
||||
type = PermissionDelegate.PERMISSION_PERSISTENT_STORAGE;
|
||||
} else if ("xr".equals(typeString)) {
|
||||
type = PermissionDelegate.PERMISSION_XR;
|
||||
} else if ("midi".equals(typeString)) {
|
||||
// We can get this from WPT and presumably other content, but Gecko
|
||||
// doesn't support Web MIDI.
|
||||
|
@ -4961,12 +4959,6 @@ public class GeckoSession implements Parcelable {
|
|||
*/
|
||||
int PERMISSION_PERSISTENT_STORAGE = 2;
|
||||
|
||||
/**
|
||||
* Permission for using the WebXR API.
|
||||
* See: https://www.w3.org/TR/webxr
|
||||
*/
|
||||
int PERMISSION_XR = 3;
|
||||
|
||||
/**
|
||||
* Callback interface for notifying the result of a permission request.
|
||||
*/
|
||||
|
@ -5018,7 +5010,6 @@ public class GeckoSession implements Parcelable {
|
|||
* PERMISSION_GEOLOCATION
|
||||
* PERMISSION_DESKTOP_NOTIFICATION
|
||||
* PERMISSION_PERSISTENT_STORAGE
|
||||
* PERMISSION_XR
|
||||
* @param callback Callback interface.
|
||||
*/
|
||||
@UiThread
|
||||
|
@ -5216,8 +5207,7 @@ public class GeckoSession implements Parcelable {
|
|||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({PermissionDelegate.PERMISSION_GEOLOCATION,
|
||||
PermissionDelegate.PERMISSION_DESKTOP_NOTIFICATION,
|
||||
PermissionDelegate.PERMISSION_XR})
|
||||
PermissionDelegate.PERMISSION_DESKTOP_NOTIFICATION})
|
||||
/* package */ @interface Permission {}
|
||||
|
||||
/**
|
||||
|
|
|
@ -62,8 +62,6 @@ exclude: true
|
|||
accept a JSON object instead of a Map. Said object also includes the
|
||||
application name that was previously passed as the fourth argument to the
|
||||
method, which was thus removed.
|
||||
- Added WebXR device access permission support, [`PERMISSION_PERSISTENT_XR`][72.24].
|
||||
([bug 1599927]({{bugzilla}}1599927))
|
||||
|
||||
[72.1]: {{javadoc_uri}}/GeckoSession.NavigationDelegate.LoadRequest#hasUserGesture-
|
||||
[72.2]: {{javadoc_uri}}/Autofill.html
|
||||
|
@ -88,7 +86,6 @@ exclude: true
|
|||
[72.21]: {{javadoc_uri}}/WebExtension.Icon.html
|
||||
[72.22]: {{javadoc_uri}}/GeckoWebExecutor.html#FETCH_FLAGS_STREAM_FAILURE_TEST
|
||||
[72.23]: {{javadoc_uri}}/CrashReporter#sendCrashReport-android.content.Context-java.io.File-org.json.JSONObject-
|
||||
[72.24]: {{javadoc_uri}}/GeckoSession.PermissionDelegate.html#PERMISSION_PERSISTENT_XR
|
||||
|
||||
## v71
|
||||
- Added a content blocking flag for blocked social cookies to [`ContentBlocking`][70.17].
|
||||
|
|
|
@ -1186,8 +1186,6 @@ public class GeckoViewActivity
|
|||
}
|
||||
resId = R.string.request_storage;
|
||||
contentPermissionCallback = new ExamplePersistentStorageCallback(callback, uri);
|
||||
} else if (PERMISSION_XR == type) {
|
||||
resId = R.string.request_xr;
|
||||
} else {
|
||||
Log.w(LOGTAG, "Unknown permission: " + type);
|
||||
callback.reject();
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
<string name="request_video">Share video with "%1$s"</string>
|
||||
<string name="request_audio">Share audio with "%1$s"</string>
|
||||
<string name="request_media">Share video and audio with "%1$s"</string>
|
||||
<string name="request_xr">Share WebXR displays with "%1$s"?</string>
|
||||
<string name="media_back_camera">Back camera</string>
|
||||
<string name="media_front_camera">Front camera</string>
|
||||
<string name="media_microphone">Microphone</string>
|
||||
|
|
|
@ -1,3 +1 @@
|
|||
prefs: [dom.vr.enabled:true,
|
||||
dom.vr.prompt.testing:true, dom.vr.prompt.testing.allow:true, dom.security.featurePolicy.experimental.enabled:true,
|
||||
dom.security.featurePolicy.enabled:true, dom.security.featurePolicy.header.enabled:true, dom.security.featurePolicy.webidl.enabled:true]
|
||||
prefs: [dom.vr.enabled:true, dom.security.featurePolicy.enabled:true, dom.security.featurePolicy.experimental.enabled:true, dom.security.featurePolicy.header.enabled:true, dom.security.featurePolicy.webidl.enabled:true]
|
||||
|
|
Загрузка…
Ссылка в новой задаче