Commit 3adbed21 authored by Mikhail Pozdnyakov's avatar Mikhail Pozdnyakov Committed by Commit Bot

[DeviceOrientation]Blink-side Feature Policy check

DeviceSingleWindowEventController::DidAddEventListener() is not
called if {deviceorientation|deviceorientationabsolute|devicemotion}
events are blocked by feature policy.

A console message referencing to
https://github.com/WICG/feature-policy/blob/gh-pages/features.md
is send to warn the user.

Bug: 796894
Change-Id: I350ff75ca55766b7ebb42944d66470ecd2b8a4c1
Reviewed-on: https://chromium-review.googlesource.com/870510Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Reviewed-by: default avatarTim Volodine <timvolodine@chromium.org>
Reviewed-by: default avatarReilly Grant <reillyg@chromium.org>
Commit-Queue: Mikhail Pozdnyakov <mikhail.pozdnyakov@intel.com>
Cr-Commit-Position: refs/heads/master@{#532384}
parent 4c7ec5bf
......@@ -472,8 +472,8 @@ IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest,
// Main frame is on a.com, iframe is on b.com.
GURL main_frame_url =
https_embedded_test_server_->GetURL("a.com", "/cross_origin_iframe.html");
GURL iframe_url =
https_embedded_test_server_->GetURL("b.com", "/device_motion_test.html");
GURL iframe_url = https_embedded_test_server_->GetURL(
"b.com", "/device_motion_test.html?failure_timeout=100");
// Wait for the main frame, subframe, and the #pass/#fail commits.
TestNavigationObserver navigation_observer(shell()->web_contents(), 3);
......@@ -523,7 +523,7 @@ IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest,
GURL main_frame_url =
https_embedded_test_server_->GetURL("a.com", "/cross_origin_iframe.html");
GURL iframe_url = https_embedded_test_server_->GetURL(
"b.com", "/device_orientation_test.html");
"b.com", "/device_orientation_test.html?failure_timeout=100");
// Wait for the main frame, subframe, and the #pass/#fail commits.
TestNavigationObserver navigation_observer(shell()->web_contents(), 3);
......@@ -567,6 +567,32 @@ IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest,
EXPECT_EQ("pass", iframe->GetLastCommittedURL().ref());
}
IN_PROC_BROWSER_TEST_F(DeviceSensorBrowserTest,
DeviceOrientationFeaturePolicyWarning) {
// Main frame is on a.com, iframe is on b.com.
GURL main_frame_url =
https_embedded_test_server_->GetURL("a.com", "/cross_origin_iframe.html");
GURL iframe_url = https_embedded_test_server_->GetURL(
"b.com", "/device_orientation_absolute_test.html");
const char kWarningMessage[] =
"The deviceorientationabsolute events are blocked by "
"feature policy. See "
"https://github.com/WICG/feature-policy/blob/"
"gh-pages/features.md#sensor-features";
auto console_delegate = std::make_unique<ConsoleObserverDelegate>(
shell()->web_contents(), kWarningMessage);
shell()->web_contents()->SetDelegate(console_delegate.get());
EXPECT_TRUE(NavigateToURL(shell(), main_frame_url));
EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(),
"cross_origin_iframe", iframe_url));
console_delegate->Wait();
EXPECT_EQ(kWarningMessage, console_delegate->message());
}
} // namespace
} // namespace content
......@@ -2,8 +2,10 @@
<head>
<title>DeviceMotion test</title>
<script type="text/javascript">
let expectedInterval = Math.floor(1000 / 60);
let kRadiansToDegrees = 180 / Math.PI;
const expectedInterval = Math.floor(1000 / 60);
const kRadiansToDegrees = 180 / Math.PI;
let eventTimeoutId; // To be set in start().
function checkMotionEvent(event) {
return event.acceleration.x == 1 &&
event.acceleration.y == 2 &&
......@@ -20,6 +22,7 @@
function onMotion(event) {
if (checkMotionEvent(event)) {
window.removeEventListener('devicemotion', onMotion);
window.clearTimeout(eventTimeoutId);
pass();
} else {
fail();
......@@ -34,9 +37,21 @@
function fail() {
document.location = '#fail';
}
function failOnTimeoutIfNeeded() {
let params = new URLSearchParams(location.search);
let timeout = Number(params.get("failure_timeout"));
if (timeout > 0)
eventTimeoutId = window.setTimeout(fail, timeout);
}
function start() {
window.addEventListener('devicemotion', onMotion);
failOnTimeoutIfNeeded();
}
</script>
</head>
<body onLoad="window.addEventListener('devicemotion', onMotion)">
<body onLoad="start()">
<div id="status">FAIL</div>
</body>
</html>
......@@ -2,6 +2,8 @@
<head>
<title>DeviceOrientation test</title>
<script type="text/javascript">
let eventTimeoutId; // To be set in start().
function checkOrientationEvent(event) {
// Return true iff the orientation is close enough to (1, 2, 3).
return Math.abs(event.alpha - 1) < 0.01 &&
......@@ -13,6 +15,7 @@
function onOrientation(event) {
if (checkOrientationEvent(event)) {
window.removeEventListener('deviceorientation', onOrientation);
window.clearTimeout(eventTimeoutId);
pass();
} else {
fail();
......@@ -27,9 +30,21 @@
function fail() {
document.location = '#fail';
}
function failOnTimeoutIfNeeded() {
let params = new URLSearchParams(location.search);
let timeout = Number(params.get("failure_timeout"));
if (timeout > 0)
eventTimeoutId = window.setTimeout(fail, timeout);
}
function start() {
window.addEventListener('deviceorientation', onOrientation);
failOnTimeoutIfNeeded();
}
</script>
</head>
<body onLoad="window.addEventListener('deviceorientation', onOrientation)">
<body onLoad="start()">
<div id="status">FAIL</div>
</body>
</html>
......@@ -90,6 +90,17 @@ bool DeviceSingleWindowEventController::IsSameSecurityOriginAsMainFrame()
return false;
}
bool DeviceSingleWindowEventController::CheckPolicyFeatures(
const Vector<FeaturePolicyFeature>& features) const {
LocalFrame* frame = GetDocument().GetFrame();
if (!frame)
return false;
return std::all_of(features.begin(), features.end(),
[frame](FeaturePolicyFeature feature) {
return frame->IsFeatureEnabled(feature);
});
}
void DeviceSingleWindowEventController::Trace(blink::Visitor* visitor) {
visitor->Trace(document_);
PlatformEventController::Trace(visitor);
......
......@@ -36,6 +36,7 @@ class CORE_EXPORT DeviceSingleWindowEventController
Document& GetDocument() const { return *document_; }
bool IsSameSecurityOriginAsMainFrame() const;
bool CheckPolicyFeatures(const Vector<FeaturePolicyFeature>& features) const;
void DispatchDeviceEvent(Event*);
......
......@@ -11,6 +11,7 @@
#include "modules/device_orientation/DeviceMotionData.h"
#include "modules/device_orientation/DeviceMotionDispatcher.h"
#include "modules/device_orientation/DeviceMotionEvent.h"
#include "modules/device_orientation/DeviceOrientationController.h"
#include "platform/weborigin/SecurityOrigin.h"
#include "public/platform/Platform.h"
......@@ -42,20 +43,17 @@ void DeviceMotionController::DidAddEventListener(
if (event_type != EventTypeName())
return;
if (GetDocument().GetFrame()) {
LocalFrame* frame = GetDocument().GetFrame();
if (frame) {
if (GetDocument().IsSecureContext()) {
UseCounter::Count(GetDocument().GetFrame(),
WebFeature::kDeviceMotionSecureOrigin);
UseCounter::Count(frame, WebFeature::kDeviceMotionSecureOrigin);
} else {
Deprecation::CountDeprecation(GetDocument().GetFrame(),
Deprecation::CountDeprecation(frame,
WebFeature::kDeviceMotionInsecureOrigin);
HostsUsingFeatures::CountAnyWorld(
GetDocument(),
HostsUsingFeatures::Feature::kDeviceMotionInsecureHost);
if (GetDocument()
.GetFrame()
->GetSettings()
->GetStrictPowerfulFeatureRestrictions())
if (frame->GetSettings()->GetStrictPowerfulFeatureRestrictions())
return;
}
}
......@@ -68,6 +66,13 @@ void DeviceMotionController::DidAddEventListener(
Platform::Current()->RecordRapporURL(
"DeviceSensors.DeviceMotionCrossOrigin", WebURL(GetDocument().Url()));
}
if (!CheckPolicyFeatures({FeaturePolicyFeature::kAccelerometer,
FeaturePolicyFeature::kGyroscope})) {
DeviceOrientationController::LogToConsolePolicyFeaturesDisabled(
frame, EventTypeName());
return;
}
}
DeviceSingleWindowEventController::DidAddEventListener(window, event_type);
......
......@@ -41,25 +41,31 @@ void DeviceOrientationAbsoluteController::DidAddEventListener(
if (event_type != EventTypeName())
return;
if (GetDocument().GetFrame()) {
LocalFrame* frame = GetDocument().GetFrame();
if (frame) {
if (GetDocument().IsSecureContext()) {
UseCounter::Count(GetDocument().GetFrame(),
UseCounter::Count(frame,
WebFeature::kDeviceOrientationAbsoluteSecureOrigin);
} else {
Deprecation::CountDeprecation(
GetDocument().GetFrame(),
WebFeature::kDeviceOrientationAbsoluteInsecureOrigin);
frame, WebFeature::kDeviceOrientationAbsoluteInsecureOrigin);
// TODO: add rappor logging of insecure origins as in
// DeviceOrientationController.
if (GetDocument()
.GetFrame()
->GetSettings()
->GetStrictPowerfulFeatureRestrictions())
if (frame->GetSettings()->GetStrictPowerfulFeatureRestrictions())
return;
}
}
// TODO: add rappor url logging as in DeviceOrientationController.
if (!has_event_listener_) {
// TODO: add rappor url logging as in DeviceOrientationController.
if (!CheckPolicyFeatures({FeaturePolicyFeature::kAccelerometer,
FeaturePolicyFeature::kGyroscope,
FeaturePolicyFeature::kMagnetometer})) {
LogToConsolePolicyFeaturesDisabled(frame, EventTypeName());
return;
}
}
DeviceSingleWindowEventController::DidAddEventListener(window, event_type);
}
......
......@@ -5,12 +5,15 @@
#include "modules/device_orientation/DeviceOrientationController.h"
#include "core/frame/Deprecation.h"
#include "core/frame/FrameConsole.h"
#include "core/frame/HostsUsingFeatures.h"
#include "core/frame/Settings.h"
#include "core/inspector/ConsoleMessage.h"
#include "modules/EventModules.h"
#include "modules/device_orientation/DeviceOrientationData.h"
#include "modules/device_orientation/DeviceOrientationDispatcher.h"
#include "modules/device_orientation/DeviceOrientationEvent.h"
#include "platform/feature_policy/FeaturePolicy.h"
#include "platform/weborigin/SecurityOrigin.h"
#include "platform/wtf/Assertions.h"
#include "public/platform/Platform.h"
......@@ -51,14 +54,13 @@ void DeviceOrientationController::DidAddEventListener(
if (event_type != EventTypeName())
return;
if (GetDocument().GetFrame()) {
LocalFrame* frame = GetDocument().GetFrame();
if (frame) {
if (GetDocument().IsSecureContext()) {
UseCounter::Count(GetDocument().GetFrame(),
WebFeature::kDeviceOrientationSecureOrigin);
UseCounter::Count(frame, WebFeature::kDeviceOrientationSecureOrigin);
} else {
Deprecation::CountDeprecation(
GetDocument().GetFrame(),
WebFeature::kDeviceOrientationInsecureOrigin);
frame, WebFeature::kDeviceOrientationInsecureOrigin);
HostsUsingFeatures::CountAnyWorld(
GetDocument(),
HostsUsingFeatures::Feature::kDeviceOrientationInsecureHost);
......@@ -79,6 +81,12 @@ void DeviceOrientationController::DidAddEventListener(
"DeviceSensors.DeviceOrientationCrossOrigin",
WebURL(GetDocument().Url()));
}
if (!CheckPolicyFeatures({FeaturePolicyFeature::kAccelerometer,
FeaturePolicyFeature::kGyroscope})) {
LogToConsolePolicyFeaturesDisabled(frame, EventTypeName());
return;
}
}
DeviceSingleWindowEventController::DidAddEventListener(window, event_type);
......@@ -141,4 +149,21 @@ void DeviceOrientationController::Trace(blink::Visitor* visitor) {
Supplement<Document>::Trace(visitor);
}
// static
void DeviceOrientationController::LogToConsolePolicyFeaturesDisabled(
LocalFrame* frame,
const AtomicString& event_name) {
if (!frame)
return;
const String& message = String::Format(
"The %s events are blocked by feature policy. "
"See "
"https://github.com/WICG/feature-policy/blob/gh-pages/"
"features.md#sensor-features",
event_name.Ascii().data());
ConsoleMessage* console_message = ConsoleMessage::Create(
kJSMessageSource, kWarningMessageLevel, std::move(message));
frame->Console().AddMessage(console_message);
}
} // namespace blink
......@@ -35,6 +35,10 @@ class MODULES_EXPORT DeviceOrientationController
virtual void Trace(blink::Visitor*);
static void LogToConsolePolicyFeaturesDisabled(
LocalFrame*,
const AtomicString& event_name);
protected:
explicit DeviceOrientationController(Document&);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment