Skip to content

Commit

Permalink
Remove navigator.vibrate without user gesture.
Browse files Browse the repository at this point in the history
Calls to navigator.vibrate will immediately return 'false' if user
hasn't tapped on the frame or any embedded frame yet.

The implementation is behind an experimental flag.

The Intent to Deprecate thread:
https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/QGcpjisxtik

BUG=704650

Review-Url: https://codereview.chromium.org/2778693004
Cr-Commit-Position: refs/heads/master@{#465618}
(cherry picked from commit c5b5911)

Review-Url: https://codereview.chromium.org/2825403002 .
Cr-Commit-Position: refs/branch-heads/3071@{#54}
Cr-Branched-From: a106f0a-refs/heads/master@{#464641}
  • Loading branch information
gogerald committed Apr 19, 2017
1 parent 338ccfc commit 54365e6
Show file tree
Hide file tree
Showing 40 changed files with 410 additions and 80 deletions.
4 changes: 4 additions & 0 deletions chrome/browser/about_flags.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2304,6 +2304,10 @@ const FeatureEntry kFeatureEntries[] = {
flag_descriptions::kFramebustingName,
flag_descriptions::kFramebustingDescription, kOsAll,
FEATURE_VALUE_TYPE(features::kFramebustingNeedsSameOriginOrUserGesture)},
{"vibrate-requires-user-gesture",
flag_descriptions::kVibrateRequiresUserGestureName,
flag_descriptions::kVibrateRequiresUserGestureDescription, kOsAll,
FEATURE_VALUE_TYPE(features::kVibrateRequiresUserGesture)},
{"web-payments", flag_descriptions::kWebPaymentsName,
flag_descriptions::kWebPaymentsDescription, kOsDesktop,
FEATURE_VALUE_TYPE(features::kWebPayments)},
Expand Down
7 changes: 7 additions & 0 deletions chrome/browser/flag_descriptions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2508,6 +2508,13 @@ const char kFramebustingDescription[] =
"unless they are same-origin or the iframe is processing a user "
"gesture.";

const char kVibrateRequiresUserGestureName[] =
"Requiring user gesture for the Vibration API";

const char kVibrateRequiresUserGestureDescription[] =
"Block the Vibration API if no user gesture has been received on "
"the frame or any embedded frame.";

#if defined(OS_ANDROID)

const char kEnableVrShellName[] = "Enable Chrome VR.";
Expand Down
6 changes: 6 additions & 0 deletions chrome/browser/flag_descriptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,12 @@ extern const char kTouchSelectionStrategyCharacter[];
// direction in which the handle is dragged.
extern const char kTouchSelectionStrategyDirection[];

// Name of the flag that requires a user gesture for vibrate.
extern const char kVibrateRequiresUserGestureName[];

// Description of the flag that requires a user gesture for vibrate.
extern const char kVibrateRequiresUserGestureDescription[];

// Title for the flag to use the Online Wallet sandbox servers (instead of
// production).
extern const char kWalletServiceUseSandboxName[];
Expand Down
4 changes: 4 additions & 0 deletions content/child/runtime_features.cc
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,10 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
base::FeatureList::IsEnabled(
features::kFramebustingNeedsSameOriginOrUserGesture));

WebRuntimeFeatures::EnableFeatureFromString(
"VibrateRequiresUserGesture",
base::FeatureList::IsEnabled(features::kVibrateRequiresUserGesture));

if (command_line.HasSwitch(switches::kDisableBackgroundTimerThrottling))
WebRuntimeFeatures::EnableTimerThrottlingForBackgroundTabs(false);

Expand Down
4 changes: 4 additions & 0 deletions content/public/common/content_features.cc
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,10 @@ const base::Feature kTokenBinding{"token-binding",
const base::Feature kTouchpadAndWheelScrollLatching{
"TouchpadAndWheelScrollLatching", base::FEATURE_DISABLED_BY_DEFAULT};

// Controls whether vibrate requires user gesture.
const base::Feature kVibrateRequiresUserGesture{
"VibrateRequiresUserGesture", base::FEATURE_DISABLED_BY_DEFAULT};

// Enables VR UI.
const base::Feature kVrShell{"VrShell", base::FEATURE_DISABLED_BY_DEFAULT};

Expand Down
1 change: 1 addition & 0 deletions content/public/common/content_features.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ CONTENT_EXPORT extern const base::Feature kSlimmingPaintInvalidation;
CONTENT_EXPORT extern const base::Feature kTimerThrottlingForHiddenFrames;
CONTENT_EXPORT extern const base::Feature kTokenBinding;
CONTENT_EXPORT extern const base::Feature kTouchpadAndWheelScrollLatching;
CONTENT_EXPORT extern const base::Feature kVibrateRequiresUserGesture;
CONTENT_EXPORT extern const base::Feature kVrShell;
CONTENT_EXPORT extern const base::Feature kWebAssembly;
CONTENT_EXPORT extern const base::Feature kWebGLImageChromium;
Expand Down
11 changes: 11 additions & 0 deletions third_party/WebKit/LayoutTests/TestExpectations
Original file line number Diff line number Diff line change
Expand Up @@ -2608,3 +2608,14 @@ crbug.com/707689 shapedetection/detection-HTMLCanvasElement.html [ Skip ]
crbug.com/682753 fast/canvas-experimental [ Skip ]

crbug.com/708934 fast/backgrounds/background-image-relative-url-in-iframe.html [ Failure Pass ]

# Skip tests for vibrate with feature policy
crbug.com/710850 http/tests/feature-policy/vibrate-enabledforall.php [ Skip ]
crbug.com/710850 http/tests/feature-policy/vibrate-enabledforself.php [ Skip ]
crbug.com/710850 http/tests/feature-policy/vibrate-disabled.php [ Skip ]
crbug.com/710850 virtual/feature-policy/http/tests/feature-policy/vibrate-enabledforall.php [ Skip ]
crbug.com/710850 virtual/feature-policy/http/tests/feature-policy/vibrate-enabledforself.php [ Skip ]
crbug.com/710850 virtual/feature-policy/http/tests/feature-policy/vibrate-disabled.php [ Skip ]
crbug.com/710850 virtual/mojo-loading/http/tests/feature-policy/vibrate-enabledforall.php [ Skip ]
crbug.com/710850 virtual/mojo-loading/http/tests/feature-policy/vibrate-enabledforself.php [ Skip ]
crbug.com/710850 virtual/mojo-loading/http/tests/feature-policy/vibrate-disabled.php [ Skip ]
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,23 @@
<title>Feature-Policy Vibrate Disabled</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<script src="/js-test-resources/user-gesture-utils.js"></script>
<script>
test(function() {

function startTest(event) {
// Simulates a user click for vibrate to be allowed.
var element = document.getElementById("test");
simulateUserClick(element.offsetLeft + event.data.x + 2, element.offsetTop + event.data.y + 2);
}

function testVibrate() {
test(function () {
assert_false(navigator.vibrate(200));
}, 'No iframe may call navigator.vibrate when disabled.');
}

window.addEventListener("message", startTest, true);
</script>
<body>
<button id="test" onclick="testVibrate();">Click to vibrate</button>

Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
<!DOCTYPE html>
<head>
<title>Feature-Policy Vibrate Enabled</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<title>Feature-Policy Vibrate Enabled</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/js-test-resources/user-gesture-utils.js"></script>
<script>
test(function() {
assert_true(navigator.vibrate(200));

function startTest(event) {
// Simulates a user click for vibrate to be allowed.
var element = document.getElementById("test");
simulateUserClick(element.offsetLeft + event.data.x + 2, element.offsetTop + event.data.y + 2);
}

function testVibrate() {
test(function () {
assert_true(navigator.vibrate(200));
}, 'Any iframe may call navigator.vibrate when enabled.');
}

window.addEventListener("message", startTest, false);
</script>
<body>
<button id="test" onclick="testVibrate();">Click to vibrate</button>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
CONSOLE ERROR: line 9: Blocked call to navigator.vibrate because user hasn't tapped on the frame or any embedded frame yet: https://www.chromestatus.com/feature/5644273861001216.


--------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,22 @@
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script>
if (window.testRunner) {
testRunner.dumpAsText();
testRunner.dumpChildFramesAsText();
if (window.testRunner) {
testRunner.dumpAsText();
testRunner.dumpChildFramesAsText();
}

function loaded() {
var iframes = document.getElementsByTagName('iframe');
for (var i = 0; i < iframes.length; ++i) { // < 1; ++i) { //
var iframe = iframes[i];
// The iframe uses eventSender to emulate a user navigatation, which requires absolute coordinates.
iframe.contentWindow.postMessage({x: iframe.offsetLeft, y: iframe.offsetTop}, "*");
}
}
</script>
</head>
<body>
<body onload="loaded();">
<iframe id="f1" src="resources/feature-policy-vibrate-enabled.html"></iframe>
<iframe id="f2" src="http://localhost:8000/feature-policy/resources/feature-policy-vibrate-enabled.html"></iframe>
</body>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,22 @@
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script>
if (window.testRunner) {
testRunner.dumpAsText();
testRunner.dumpChildFramesAsText();
if (window.testRunner) {
testRunner.dumpAsText();
testRunner.dumpChildFramesAsText();
}

function loaded() {
var iframes = document.getElementsByTagName('iframe');
for (var i = 0; i < iframes.length; ++i) {
var iframe = iframes[i];
// The iframe uses eventSender to emulate a user navigatation, which requires absolute coordinates.
iframe.contentWindow.postMessage({x: iframe.offsetLeft, y: iframe.offsetTop}, "*");
}
}
</script>
</head>
<body>
<body onload="loaded();">
<iframe id="f1" src="resources/feature-policy-vibrate-enabled.html"></iframe>
<iframe id="f2" src="http://localhost:8000/feature-policy/resources/feature-policy-vibrate-disabled.html"></iframe>
</body>
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,48 +1,41 @@
<html>
<head>
<title>Testing vibrate 3 times in an iframe</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/js-test-resources/user-gesture-utils.js"></script>
<script>
var test = async_test(
"Testing vibrate 3 times in a x-origin iframe: " +
" 1. blocked before user gesture;" +
" 2. succeed during the click event;" +
" 3. succeed after user click.");
function loaded()
{
document.getElementsByTagName('h4')[0].innerHTML = document.domain;
}

function startTest(event)
{
// A manual click should navigate.
// A manual click should enable vibrate.
if (window.eventSender) {
var button = document.getElementById("b");
eventSender.mouseMoveTo(button.offsetLeft + event.data.x + 2, button.offsetTop + event.data.y + 2);
test.step(function() {
test(function() {
assert_false(
navigator.vibrate(200),
"1. Blocked vibrate before user gesture.");
});

eventSender.mouseDown();
eventSender.mouseUp();
var element = document.getElementById("b");
simulateUserClick(element.offsetLeft + event.data.x + 2, element.offsetTop + event.data.y + 2);
}
}

function performTestAfterClick()
{
test.step(function () {
test(function () {
assert_true(
navigator.vibrate(200),
"3. Vibrate after user gesture succeeded.");
});
test.done();
}

function performTestWithClick()
{
test.step(function () {
test(function () {
assert_true(
navigator.vibrate(200),
"2. Vibrate triggered by user gesture succeeded.");
Expand All @@ -58,3 +51,4 @@ <h4>DOMAIN</h4>
<button id="b" onclick="performTestWithClick();">Perform Test</button>
</body>
</html>

Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<html>
<head>
<title>Testing vibrate 3 times in an iframe</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/js-test-resources/user-gesture-utils.js"></script>
<script>
function loaded()
{
document.getElementsByTagName('h4')[0].innerHTML = document.domain;
}

function startTest(event)
{
// A manual click should enable vibrate.
if (window.eventSender) {
test(function() {
assert_true(
navigator.vibrate(200),
"1. Vibrate w/o user gesture is deprecated and will be blocked in M60.");
});
var element = document.getElementById("b");
simulateUserClick(element.offsetLeft + event.data.x + 2, element.offsetTop + event.data.y + 2);
}
}

function performTestAfterClick()
{
test(function () {
assert_true(
navigator.vibrate(200),
"3. Vibrate after user gesture succeeded.");
});
}

function performTestWithClick()
{
test(function () {
assert_true(
navigator.vibrate(200),
"2. Vibrate triggered by user gesture succeeded.");
});
window.requestAnimationFrame(performTestAfterClick);
}

window.addEventListener("message", startTest, false);
</script>
</head>
<body onload="loaded();">
<h4>DOMAIN</h4>
<button id="b" onclick="performTestWithClick();">Perform Test</button>
</body>
</html>

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/js-test-resources/user-gesture-utils.js"></script>
<script>

function startTest(event) {
// Simulates a user click for vibrate to be allowed.
var element = document.getElementById("test");
simulateUserClick(element.offsetLeft + event.data.x + 2, element.offsetTop + event.data.y + 2);
}

function testVibrate() {
test(function () {
assert_true(navigator.vibrate(200));
}, "An iframe may call navigator.vibrate with user gesture.");
}

window.addEventListener("message", startTest, false);
</script>
</head>
<body>
<button id="test" onclick="testVibrate();">Click to vibrate</button>
</body>
</html>
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@
}
</script>
</head>
<iframe id="iframe" src="http://localhost:8000/security/resources/cross-origin-iframe-for-vibrate-blocked.html"></iframe>
<iframe id="iframe" src="http://localhost:8000/security/vibration/resources/vibrate-in-cross-origin-iframe-blocked.html"></iframe>
</html>
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CONSOLE ERROR: line 24: Blocked call to navigator.vibrate inside a cross-origin iframe because the frame has never been activated by the user: https://www.chromestatus.com/feature/5682658461876224.
CONSOLE ERROR: line 19: Blocked call to navigator.vibrate inside a cross-origin iframe because the frame has never been activated by the user: https://www.chromestatus.com/feature/5682658461876224.
This tests that a cross-origin iframe with user gesture can vibrate.

127.0.0.1
Expand All @@ -9,6 +9,6 @@ This tests that a cross-origin iframe with user gesture can vibrate.
Frame: '<!--framePath //<!--frame0-->-->'
--------
This is a testharness.js-based test.
PASS Testing vibrate 3 times in a x-origin iframe: 1. blocked before user gesture; 2. succeed during the click event; 3. succeed after user click.
PASS Testing vibrate 3 times in an iframe
Harness: the test ran to completion.

Loading

0 comments on commit 54365e6

Please sign in to comment.