Add vr feature policy
This CL enables vr feature policy. So that, if you want to disable vr within
your application, you can delivering the following HTTP response header:
Feature-Policy: vr 'none'
If you want to enable vr for all frames(including cross-origin iframes),
delivering this:
Feature-Policy: vr *
If you want to enable vr just for your own origin, delivering this:
Feature-Policy: vr 'self'
To request vr for iframes, you can
<iframe src="https://foo.bar" allow="vr"></iframe> to grant vr to this iframe.
Bug: 666767
Change-Id: I48d7accf8553d6a9ac19d9f41dbbce2ff9934579
Reviewed-on: https://chromium-review.googlesource.com/636663
Reviewed-by: Ian Vollick <vollick@chromium.org>
Reviewed-by: Michael Thiessen <mthiesse@chromium.org>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: Brandon Jones <bajones@chromium.org>
Reviewed-by: Ian Clelland <iclelland@chromium.org>
Commit-Queue: Biao She <bshe@chromium.org>
Cr-Commit-Position: refs/heads/master@{#498674}
diff --git a/content/common/feature_policy/feature_policy.cc b/content/common/feature_policy/feature_policy.cc
index 6d82e7b..8255175 100644
--- a/content/common/feature_policy/feature_policy.cc
+++ b/content/common/feature_policy/feature_policy.cc
@@ -235,6 +235,8 @@
{blink::WebFeaturePolicyFeature::kSyncXHR,
FeaturePolicy::FeatureDefault::EnableForAll},
{blink::WebFeaturePolicyFeature::kUsb,
+ FeaturePolicy::FeatureDefault::EnableForSelf},
+ {blink::WebFeaturePolicyFeature::kWebVr,
FeaturePolicy::FeatureDefault::EnableForSelf}}));
return default_feature_list;
}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/resources/feature-policy-webvr.html b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/resources/feature-policy-webvr.html
new file mode 100644
index 0000000..64a152b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/resources/feature-policy-webvr.html
@@ -0,0 +1,9 @@
+<script>
+'use strict';
+
+Promise.resolve().then(() => navigator.getVRDisplays()).then(displays => {
+ window.parent.postMessage({ enabled: true }, '*');
+}, error => {
+ window.parent.postMessage({ enabled: false }, '*');
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webvr/webvr-disabled-by-feature-policy.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/webvr/webvr-disabled-by-feature-policy.https.sub.html
new file mode 100644
index 0000000..567499c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/webvr/webvr-disabled-by-feature-policy.https.sub.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<body>
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src=/feature-policy/resources/featurepolicy.js></script>
+
+ <script>
+ 'use strict';
+ var same_origin_src = '/feature-policy/resources/feature-policy-webvr.html';
+ var cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+ same_origin_src;
+ var header = 'Feature-Policy header vr "none"';
+
+ promise_test(() => {
+ return navigator.getVRDisplays().then(() => {
+ assert_unreached('expected promise to reject');
+ }, error => {
+ });
+ }, header + ' disallows the top-level document.');
+
+ async_test(t => {
+ test_feature_availability(
+ 'navigator.getVRDisplays()', t, same_origin_src,
+ expect_feature_unavailable_default);
+ }, header + ' disallows same-origin iframes.');
+
+ async_test(t => {
+ test_feature_availability(
+ 'navigator.getVRDisplays()', t, cross_origin_src,
+ expect_feature_unavailable_default);
+ }, header + ' disallows cross-origin iframes.');
+ </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webvr/webvr-disabled-by-feature-policy.https.sub.html.headers b/third_party/WebKit/LayoutTests/external/wpt/webvr/webvr-disabled-by-feature-policy.https.sub.html.headers
new file mode 100644
index 0000000..d021af7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/webvr/webvr-disabled-by-feature-policy.https.sub.html.headers
@@ -0,0 +1 @@
+Feature-Policy: vr 'none'
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webvr/webvr-enabled-by-feature-policy-attribute-redirect-on-load.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/webvr/webvr-enabled-by-feature-policy-attribute-redirect-on-load.https.sub.html
new file mode 100644
index 0000000..da01dafd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/webvr/webvr-enabled-by-feature-policy-attribute-redirect-on-load.https.sub.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<body>
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src=/feature-policy/resources/featurepolicy.js></script>
+ <script>
+ 'use strict';
+ var relative_path = '/feature-policy/resources/feature-policy-webvr.html';
+ var base_src = '/feature-policy/resources/redirect-on-load.html#';
+ var same_origin_src = base_src + relative_path;
+ var cross_origin_src = base_src + 'https://{{domains[www]}}:{{ports[https][0]}}' +
+ relative_path;
+ var header = 'Feature-Policy allow="vr" attribute';
+
+ async_test(t => {
+ test_feature_availability(
+ 'navigator.getVRDisplays()', t, same_origin_src,
+ expect_feature_available_default, 'vr');
+ }, header + ' allows same-origin relocation');
+
+ async_test(t => {
+ test_feature_availability(
+ 'navigator.getVRDisplays()', t, cross_origin_src,
+ expect_feature_unavailable_default, 'vr');
+ }, header + ' disallows cross-origin relocation');
+ </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webvr/webvr-enabled-by-feature-policy-attribute.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/webvr/webvr-enabled-by-feature-policy-attribute.https.sub.html
new file mode 100644
index 0000000..d715f90
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/webvr/webvr-enabled-by-feature-policy-attribute.https.sub.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<body>
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src=/feature-policy/resources/featurepolicy.js></script>
+ <script>
+ 'use strict';
+ var same_origin_src = '/feature-policy/resources/feature-policy-webvr.html';
+ var cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+ same_origin_src;
+ var header = 'Feature-Policy allow="vr" attribute';
+
+ async_test(t => {
+ test_feature_availability(
+ 'navigator.getVRDisplays()', t, same_origin_src,
+ expect_feature_available_default, 'vr');
+ }, header + ' allows same-origin iframe');
+
+ async_test(t => {
+ test_feature_availability(
+ 'navigator.getVRDisplays()', t, cross_origin_src,
+ expect_feature_available_default, 'vr');
+ }, header + ' allows cross-origin iframe');
+ </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webvr/webvr-enabled-by-feature-policy.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/webvr/webvr-enabled-by-feature-policy.https.sub.html
new file mode 100644
index 0000000..ee02566
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/webvr/webvr-enabled-by-feature-policy.https.sub.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<body>
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src=/feature-policy/resources/featurepolicy.js></script>
+
+ <script>
+ 'use strict';
+ var same_origin_src = '/feature-policy/resources/feature-policy-webvr.html';
+ var cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+ same_origin_src;
+ var header = 'Feature-Policy header vr *';
+
+ promise_test(
+ () => navigator.getVRDisplays(),
+ header + ' allows the top-level document.');
+
+ async_test(t => {
+ test_feature_availability(
+ 'navigator.getVRDisplays()', t, same_origin_src,
+ expect_feature_available_default);
+ }, header + ' allows same-origin iframes.');
+
+ async_test(t => {
+ test_feature_availability(
+ 'navigator.getVRDisplays()', t, cross_origin_src,
+ expect_feature_available_default);
+ }, header + ' allows cross-origin iframes.');
+ </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webvr/webvr-enabled-by-feature-policy.https.sub.html.headers b/third_party/WebKit/LayoutTests/external/wpt/webvr/webvr-enabled-by-feature-policy.https.sub.html.headers
new file mode 100644
index 0000000..e7427ee
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/webvr/webvr-enabled-by-feature-policy.https.sub.html.headers
@@ -0,0 +1 @@
+Feature-Policy: vr *
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webvr/webvr-enabled-on-self-origin-by-feature-policy.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/webvr/webvr-enabled-on-self-origin-by-feature-policy.https.sub.html
new file mode 100644
index 0000000..bd7e82f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/webvr/webvr-enabled-on-self-origin-by-feature-policy.https.sub.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<body>
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src=/feature-policy/resources/featurepolicy.js></script>
+
+ <script>
+ 'use strict';
+ var same_origin_src = '/feature-policy/resources/feature-policy-webvr.html';
+ var cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+ same_origin_src;
+ var header = 'Feature-Policy header vr "self"';
+
+ promise_test(
+ () => navigator.getVRDisplays(),
+ header + ' allows the top-level document.');
+
+ async_test(t => {
+ test_feature_availability(
+ 'navigator.getVRDisplays()', t, same_origin_src,
+ expect_feature_available_default);
+ }, header + ' allows same-origin iframes.');
+
+ async_test(t => {
+ test_feature_availability(
+ 'navigator.getVRDisplays()', t, cross_origin_src,
+ expect_feature_unavailable_default);
+ }, header + ' disallows cross-origin iframes.');
+ </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webvr/webvr-enabled-on-self-origin-by-feature-policy.https.sub.html.headers b/third_party/WebKit/LayoutTests/external/wpt/webvr/webvr-enabled-on-self-origin-by-feature-policy.https.sub.html.headers
new file mode 100644
index 0000000..87d343d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/webvr/webvr-enabled-on-self-origin-by-feature-policy.https.sub.html.headers
@@ -0,0 +1 @@
+Feature-Policy: vr 'self'
diff --git a/third_party/WebKit/Source/modules/vr/NavigatorVR.cpp b/third_party/WebKit/Source/modules/vr/NavigatorVR.cpp
index c966856..e13b967 100644
--- a/third_party/WebKit/Source/modules/vr/NavigatorVR.cpp
+++ b/third_party/WebKit/Source/modules/vr/NavigatorVR.cpp
@@ -18,6 +18,7 @@
#include "modules/vr/VRDisplay.h"
#include "modules/vr/VRGetDevicesCallback.h"
#include "modules/vr/VRPose.h"
+#include "platform/feature_policy/FeaturePolicy.h"
#include "platform/wtf/PtrUtil.h"
#include "public/platform/Platform.h"
@@ -72,6 +73,23 @@
return promise;
}
+ LocalFrame* frame = GetDocument()->GetFrame();
+ // TODO(bshe): Add different error string for cases when promise is rejected.
+ if (!frame) {
+ RejectNavigatorDetached(resolver);
+ return promise;
+ }
+ if (IsSupportedInFeaturePolicy(WebFeaturePolicyFeature::kWebVr)) {
+ if (!frame->IsFeatureEnabled(WebFeaturePolicyFeature::kWebVr)) {
+ RejectNavigatorDetached(resolver);
+ return promise;
+ }
+ } else if (!frame->HasReceivedUserGesture() &&
+ frame->IsCrossOriginSubframe()) {
+ RejectNavigatorDetached(resolver);
+ return promise;
+ }
+
UseCounter::Count(*GetDocument(), WebFeature::kVRGetDisplays);
ExecutionContext* execution_context = ExecutionContext::From(script_state);
if (!execution_context->IsSecureContext())
diff --git a/third_party/WebKit/Source/platform/feature_policy/FeaturePolicy.cpp b/third_party/WebKit/Source/platform/feature_policy/FeaturePolicy.cpp
index 24a23c8..2a0f48a 100644
--- a/third_party/WebKit/Source/platform/feature_policy/FeaturePolicy.cpp
+++ b/third_party/WebKit/Source/platform/feature_policy/FeaturePolicy.cpp
@@ -189,6 +189,7 @@
case WebFeaturePolicyFeature::kFullscreen:
case WebFeaturePolicyFeature::kPayment:
case WebFeaturePolicyFeature::kUsb:
+ case WebFeaturePolicyFeature::kWebVr:
return true;
case WebFeaturePolicyFeature::kVibrate:
return RuntimeEnabledFeatures::FeaturePolicyExperimentalFeaturesEnabled();
@@ -213,6 +214,7 @@
default_feature_name_map.Set("geolocation",
WebFeaturePolicyFeature::kGeolocation);
default_feature_name_map.Set("midi", WebFeaturePolicyFeature::kMidiFeature);
+ default_feature_name_map.Set("vr", WebFeaturePolicyFeature::kWebVr);
if (RuntimeEnabledFeatures::FeaturePolicyExperimentalFeaturesEnabled()) {
default_feature_name_map.Set("vibrate",
WebFeaturePolicyFeature::kVibrate);
diff --git a/third_party/WebKit/public/platform/WebFeaturePolicyFeature.h b/third_party/WebKit/public/platform/WebFeaturePolicyFeature.h
index 2c271ba..b67f918 100644
--- a/third_party/WebKit/public/platform/WebFeaturePolicyFeature.h
+++ b/third_party/WebKit/public/platform/WebFeaturePolicyFeature.h
@@ -47,7 +47,9 @@
kUsb,
// Controls access to AOM event listeners.
kAccessibilityEvents,
- LAST_FEATURE = kAccessibilityEvents
+ // Controls use of WebVR API.
+ kWebVr,
+ LAST_FEATURE = kWebVr
};
} // namespace blink