Battery Status API: blink promise implementation and layout tests.

Implement Battery Status API using promises in blink as
according to the (modified) spec:
https://dvcs.w3.org/hg/dap/raw-file/tip/battery/Overview.html.
Using this patch the Battery Status API is accessible using:
navigator.getBattery().then(...) syntax.

Also added layout tests for the various use-cases.

BUG=122593, 360068

Review URL: https://codereview.chromium.org/329723005

git-svn-id: svn://svn.chromium.org/blink/trunk@176222 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 161d3b6f
......@@ -1072,3 +1072,5 @@ crbug.com/383596 inspector/console/console-object-preview-accessors.html [ Failu
crbug.com/384564 crypto/rsassa-pkcs1-v1_5-generate-key.html [ Pass Timeout ]
crbug.com/384950 fast/forms/submit-change-fragment.html [ Pass Timeout ]
crbug.com/384566 svg/custom/textPath-change-reference2.svg [ ImageOnlyFailure Pass ]
crbug.com/384396 [ Win ] battery-status/page-visibility.html [ Pass Failure Timeout ]
\ No newline at end of file
Test basic API definitions.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS promise is defined.
PASS promise.then is defined.
batteryStatusSuccess invoked
PASS battery is defined.
PASS battery is non-null.
PASS battery.charging is defined.
PASS battery.chargingTime is defined.
PASS battery.dischargingTime is defined.
PASS battery.level is defined.
PASS battery.charging is mockBatteryInfo.charging
PASS battery.chargingTime is mockBatteryInfo.chargingTime
PASS battery.dischargingTime is mockBatteryInfo.dischargingTime
PASS battery.level is mockBatteryInfo.level
PASS typeof battery.onchargingchange == 'object' is true
PASS typeof battery.onchargingtimechange == 'object' is true
PASS typeof battery.ondischargingtimechange == 'object' is true
PASS typeof battery.onlevelchange == 'object' is true
PASS battery.hasOwnProperty('onchargingchange') is true
PASS battery.hasOwnProperty('onchargingtimechange') is true
PASS battery.hasOwnProperty('ondischargingtimechange') is true
PASS battery.hasOwnProperty('onlevelchange') is true
PASS 'onchargingchange' in battery is true
PASS 'onchargingtimechange' in battery is true
PASS 'ondischargingtimechange' in battery is true
PASS 'onlevelchange' in battery is true
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE html>
<html>
<body>
<script src="../resources/js-test.js"></script>
<script>
description("Test basic API definitions.");
if (!window.testRunner)
debug('This test cannot be run without the TestRunner');
jsTestIsAsync = true;
var mockBatteryInfo;
function setAndFireMockBatteryInfo(charging, chargingTime, dischargingTime, level) {
mockBatteryInfo = { charging: charging,
chargingTime: chargingTime,
dischargingTime: dischargingTime,
level: level };
testRunner.didChangeBatteryStatus(charging, chargingTime, dischargingTime, level);
}
function batteryStatusSuccess(batteryManager) {
debug('batteryStatusSuccess invoked');
battery = batteryManager;
shouldBeDefined("battery");
shouldBeNonNull("battery");
shouldBeDefined("battery.charging");
shouldBeDefined("battery.chargingTime");
shouldBeDefined("battery.dischargingTime");
shouldBeDefined("battery.level");
shouldBe('battery.charging', 'mockBatteryInfo.charging');
shouldBe('battery.chargingTime', 'mockBatteryInfo.chargingTime');
shouldBe('battery.dischargingTime', 'mockBatteryInfo.dischargingTime');
shouldBe('battery.level', 'mockBatteryInfo.level');
shouldBeTrue("typeof battery.onchargingchange == 'object'");
shouldBeTrue("typeof battery.onchargingtimechange == 'object'");
shouldBeTrue("typeof battery.ondischargingtimechange == 'object'");
shouldBeTrue("typeof battery.onlevelchange == 'object'");
shouldBeTrue("battery.hasOwnProperty('onchargingchange')");
shouldBeTrue("battery.hasOwnProperty('onchargingtimechange')");
shouldBeTrue("battery.hasOwnProperty('ondischargingtimechange')");
shouldBeTrue("battery.hasOwnProperty('onlevelchange')");
shouldBeTrue("'onchargingchange' in battery");
shouldBeTrue("'onchargingtimechange' in battery");
shouldBeTrue("'ondischargingtimechange' in battery");
shouldBeTrue("'onlevelchange' in battery");
setTimeout(cleanupAndFinish, 0);
}
function cleanupAndFinish() {
// stops updating battery and clears current battery status.
window.testRunner.setPageVisibility("hidden");
finishJSTest();
}
function batteryStatusFailure() {
testFailed('failed to successfully resolve the promise');
setTimeout(cleanupAndFinish, 0);
}
promise = navigator.getBattery();
shouldBeDefined("promise");
shouldBeDefined("promise.then");
promise.then(batteryStatusSuccess, batteryStatusFailure);
setAndFireMockBatteryInfo(false, 10, 20, 0.5);
</script>
</body>
</html>
Test battery status API with multiple promises after resolve.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
resolution number 1
PASS batteryInfo is defined.
PASS mockBatteryInfo is defined.
PASS batteryInfo.charging is mockBatteryInfo.charging
PASS batteryInfo.chargingTime is mockBatteryInfo.chargingTime
PASS batteryInfo.dischargingTime is mockBatteryInfo.dischargingTime
PASS batteryInfo.level is mockBatteryInfo.level
resolution number 2
PASS batteryInfo is defined.
PASS mockBatteryInfo is defined.
PASS batteryInfo.charging is mockBatteryInfo.charging
PASS batteryInfo.chargingTime is mockBatteryInfo.chargingTime
PASS batteryInfo.dischargingTime is mockBatteryInfo.dischargingTime
PASS batteryInfo.level is mockBatteryInfo.level
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE html>
<html>
<body>
<script src="../resources/js-test.js"></script>
<script>
description("Test battery status API with multiple promises after resolve.");
if (!window.testRunner)
debug('This test cannot be run without the TestRunner');
testRunner.waitUntilDone();
jsTestIsAsync = true;
var mockBatteryInfo;
function setAndFireMockBatteryInfo(charging, chargingTime, dischargingTime, level) {
mockBatteryInfo = { charging: charging,
chargingTime: chargingTime,
dischargingTime: dischargingTime,
level: level };
testRunner.didChangeBatteryStatus(charging, chargingTime, dischargingTime, level);
}
// compare obtained battery values with the mock values
function checkBatteryInfo(batteryManager) {
batteryInfo = batteryManager;
shouldBeDefined("batteryInfo");
shouldBeDefined("mockBatteryInfo");
shouldBe('batteryInfo.charging', 'mockBatteryInfo.charging');
shouldBe('batteryInfo.chargingTime', 'mockBatteryInfo.chargingTime');
shouldBe('batteryInfo.dischargingTime', 'mockBatteryInfo.dischargingTime');
shouldBe('batteryInfo.level', 'mockBatteryInfo.level');
}
function batteryStatusFailure() {
testFailed('failed to successfully resolve the promise');
finishJSTest();
}
function batteryStatusSuccess(battery) {
debug('resolution number 1');
checkBatteryInfo(battery);
navigator.getBattery().then(
function(battery) {
debug('resolution number 2');
checkBatteryInfo(battery);
setTimeout(cleanupAndFinish, 0);
}, batteryStatusFailure);
}
function cleanupAndFinish() {
// stops updating battery and clears current battery status.
window.testRunner.setPageVisibility("hidden");
finishJSTest();
}
navigator.getBattery().then(batteryStatusSuccess, batteryStatusFailure);
setAndFireMockBatteryInfo(false, 10, 20, 0.5);
</script>
</body>
</html>
Test multiple promise resolution.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS promise1 === promise2 is false
first resolution
PASS batteryInfo is defined.
PASS mockBatteryInfo is defined.
PASS batteryInfo.charging is mockBatteryInfo.charging
PASS batteryInfo.chargingTime is mockBatteryInfo.chargingTime
PASS batteryInfo.dischargingTime is mockBatteryInfo.dischargingTime
PASS batteryInfo.level is mockBatteryInfo.level
second resolution
PASS batteryInfo is defined.
PASS mockBatteryInfo is defined.
PASS batteryInfo.charging is mockBatteryInfo.charging
PASS batteryInfo.chargingTime is mockBatteryInfo.chargingTime
PASS batteryInfo.dischargingTime is mockBatteryInfo.dischargingTime
PASS batteryInfo.level is mockBatteryInfo.level
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE html>
<html>
<body>
<script src="../resources/js-test.js"></script>
<script>
description("Test multiple promise resolution.");
if (!window.testRunner)
debug('This test cannot be run without the TestRunner');
testRunner.setCanOpenWindows();
testRunner.waitUntilDone();
jsTestIsAsync = true;
var mockBatteryInfo;
function setAndFireMockBatteryInfo(charging, chargingTime, dischargingTime, level) {
mockBatteryInfo = { charging: charging,
chargingTime: chargingTime,
dischargingTime: dischargingTime,
level: level };
testRunner.didChangeBatteryStatus(charging, chargingTime, dischargingTime, level);
}
// compare obtained battery values with the mock values
function checkBatteryInfo(batteryManager) {
batteryInfo = batteryManager;
shouldBeDefined("batteryInfo");
shouldBeDefined("mockBatteryInfo");
shouldBe('batteryInfo.charging', 'mockBatteryInfo.charging');
shouldBe('batteryInfo.chargingTime', 'mockBatteryInfo.chargingTime');
shouldBe('batteryInfo.dischargingTime', 'mockBatteryInfo.dischargingTime');
shouldBe('batteryInfo.level', 'mockBatteryInfo.level');
}
var promise1Count = 0;
var promise2Count = 0;
function batteryStatusFailure() {
testFailed('failed to successfully resolve the promise');
setTimeout(cleanupAndFinish, 0);
}
function finishIfReady() {
if (promise1Count == 1 && promise2Count == 1) {
setTimeout(cleanupAndFinish, 0);
}
}
function cleanupAndFinish() {
// stops updating battery and clears current battery status.
window.testRunner.setPageVisibility("hidden");
finishJSTest();
}
promise1 = navigator.getBattery().then(
function(battery) {
debug('first resolution');
checkBatteryInfo(battery);
promise1Count++;
finishIfReady();
}, batteryStatusFailure);
promise2 = navigator.getBattery().then(
function(battery) {
debug('second resolution');
checkBatteryInfo(battery);
promise2Count++;
finishIfReady();
}, batteryStatusFailure);
shouldBeFalse('promise1 === promise2');
setAndFireMockBatteryInfo(false, 10, 20, 0.5);
</script>
</body>
</html>
Test battery status API with multiple windows.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
resolution in window
PASS batteryInfo is defined.
PASS mockBatteryInfo is defined.
PASS batteryInfo.charging is mockBatteryInfo.charging
PASS batteryInfo.chargingTime is mockBatteryInfo.chargingTime
PASS batteryInfo.dischargingTime is mockBatteryInfo.dischargingTime
PASS batteryInfo.level is mockBatteryInfo.level
resolution in secondWindow
PASS batteryInfo is defined.
PASS mockBatteryInfo is defined.
PASS batteryInfo.charging is mockBatteryInfo.charging
PASS batteryInfo.chargingTime is mockBatteryInfo.chargingTime
PASS batteryInfo.dischargingTime is mockBatteryInfo.dischargingTime
PASS batteryInfo.level is mockBatteryInfo.level
PASS successfullyParsed is true
TEST COMPLETE
Test multiple windows with page visibility.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
first window: page is visible
resolution in window
PASS batteryInfo is defined.
PASS mockBatteryInfo is defined.
PASS batteryInfo.charging is mockBatteryInfo.charging
PASS batteryInfo.chargingTime is mockBatteryInfo.chargingTime
PASS batteryInfo.dischargingTime is mockBatteryInfo.dischargingTime
PASS batteryInfo.level is mockBatteryInfo.level
first window: page is hidden
resolution in secondWindow
PASS batteryInfo is defined.
PASS mockBatteryInfo is defined.
PASS batteryInfo.charging is mockBatteryInfo.charging
PASS batteryInfo.chargingTime is mockBatteryInfo.chargingTime
PASS batteryInfo.dischargingTime is mockBatteryInfo.dischargingTime
PASS batteryInfo.level is mockBatteryInfo.level
first window: page is visible
PASS batteryInfo is defined.
PASS mockBatteryInfo is defined.
PASS batteryInfo.charging is mockBatteryInfo.charging
PASS batteryInfo.chargingTime is mockBatteryInfo.chargingTime
PASS batteryInfo.dischargingTime is mockBatteryInfo.dischargingTime
PASS batteryInfo.level is mockBatteryInfo.level
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE html>
<html>
<body>
<script src="../resources/js-test.js"></script>
<script>
description("Test multiple windows with page visibility.");
if (!window.testRunner)
debug('This test cannot be run without the TestRunner');
testRunner.setCanOpenWindows();
testRunner.waitUntilDone();
jsTestIsAsync = true;
var mockBatteryInfo;
function setAndFireMockBatteryInfo(charging, chargingTime, dischargingTime, level) {
mockBatteryInfo = { charging: charging,
chargingTime: chargingTime,
dischargingTime: dischargingTime,
level: level };
testRunner.didChangeBatteryStatus(charging, chargingTime, dischargingTime, level);
}
// compare obtained battery values with the mock values
function checkBatteryInfo(batteryManager) {
batteryInfo = batteryManager;
shouldBeDefined("batteryInfo");
shouldBeDefined("mockBatteryInfo");
shouldBe('batteryInfo.charging', 'mockBatteryInfo.charging');
shouldBe('batteryInfo.chargingTime', 'mockBatteryInfo.chargingTime');
shouldBe('batteryInfo.dischargingTime', 'mockBatteryInfo.dischargingTime');
shouldBe('batteryInfo.level', 'mockBatteryInfo.level');
}
function batteryStatusFailure() {
testFailed('failed to successfully resolve the promise');
finishJSTest();
}
var battery;
var firstWindow = window;
var secondWindow = window.open("");
function batteryStatusSuccess(batteryManager) {
battery = batteryManager;
debug('resolution in window');
checkBatteryInfo(battery);
battery.addEventListener('levelchange', failAndFinish);
secondWindow.navigator.getBattery().then(
function(battery2) {
debug('resolution in secondWindow');
checkBatteryInfo(battery2);
setAndFireMockBatteryInfo(false, 10, 20, 0.6);
setTimeout(proceedToVisible, 100);
}, batteryStatusFailure);
firstWindow.testRunner.setPageVisibility("hidden");
debug("first window: page is hidden");
}
function proceedToVisible() {
battery.removeEventListener('levelchange', failAndFinish);
battery.addEventListener('levelchange', onLevelChange);
firstWindow.testRunner.setPageVisibility("visible");
debug("first window: page is visible");
}
function onLevelChange() {
checkBatteryInfo(battery);
setTimeout(cleanupAndFinish, 0);
}
function failAndFinish() {
testFailed('received event while the page was hidden');
setTimeout(cleanupAndFinish, 0);
}
function cleanupAndFinish() {
// stops updating battery and clears current battery status.
firstWindow.testRunner.setPageVisibility("hidden");
secondWindow.testRunner.setPageVisibility("hidden");
secondWindow.close();
finishJSTest();
}
debug("first window: page is visible");
navigator.getBattery().then(batteryStatusSuccess, batteryStatusFailure);
setAndFireMockBatteryInfo(false, 10, 20, 0.5);
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<body>
<script src="../resources/js-test.js"></script>
<script>
description("Test battery status API with multiple windows.");
if (!window.testRunner)
debug('This test cannot be run without the TestRunner');
testRunner.setCanOpenWindows();
testRunner.waitUntilDone();
jsTestIsAsync = true;
var mockBatteryInfo;
function setAndFireMockBatteryInfo(charging, chargingTime, dischargingTime, level) {
mockBatteryInfo = { charging: charging,
chargingTime: chargingTime,
dischargingTime: dischargingTime,
level: level };
testRunner.didChangeBatteryStatus(charging, chargingTime, dischargingTime, level);
}
// compare obtained battery values with the mock values
function checkBatteryInfo(batteryManager) {
batteryInfo = batteryManager;
shouldBeDefined("batteryInfo");
shouldBeDefined("mockBatteryInfo");
shouldBe('batteryInfo.charging', 'mockBatteryInfo.charging');
shouldBe('batteryInfo.chargingTime', 'mockBatteryInfo.chargingTime');
shouldBe('batteryInfo.dischargingTime', 'mockBatteryInfo.dischargingTime');
shouldBe('batteryInfo.level', 'mockBatteryInfo.level');
}
function batteryStatusFailure() {
testFailed('failed to successfully resolve the promise');
finishJSTest();
}
var firstWindow = window;
var secondWindow = window.open("");
function batteryStatusSuccess(battery) {
debug('resolution in window');
checkBatteryInfo(battery);
secondWindow.navigator.getBattery().then(
function(battery) {
debug('resolution in secondWindow');
checkBatteryInfo(battery);
setTimeout(cleanupAndFinish, 0);
}, batteryStatusFailure);
}
function cleanupAndFinish() {
// stops updating battery and clears current battery status.
firstWindow.testRunner.setPageVisibility("hidden");
secondWindow.testRunner.setPageVisibility("hidden");
secondWindow.close();
finishJSTest();
}
navigator.getBattery().then(batteryStatusSuccess, batteryStatusFailure);
setAndFireMockBatteryInfo(false, 10, 20, 0.5);
</script>
</body>
</html>
Test with page visibility.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
page is visible
PASS batteryInfo is defined.
PASS mockBatteryInfo is defined.
PASS batteryInfo.charging is mockBatteryInfo.charging
PASS batteryInfo.chargingTime is mockBatteryInfo.chargingTime
PASS batteryInfo.dischargingTime is mockBatteryInfo.dischargingTime
PASS batteryInfo.level is mockBatteryInfo.level
page is hidden
page is visible
PASS batteryInfo is defined.
PASS mockBatteryInfo is defined.
PASS batteryInfo.charging is mockBatteryInfo.charging
PASS batteryInfo.chargingTime is mockBatteryInfo.chargingTime
PASS batteryInfo.dischargingTime is mockBatteryInfo.dischargingTime
PASS batteryInfo.level is mockBatteryInfo.level
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE html>
<html>
<body>
<script src="../resources/js-test.js"></script>
<script>
description("Test with page visibility.");
window.jsTestIsAsync = true;
if (!window.testRunner)
debug('This test cannot be run without the TestRunner');
var mockBatteryInfo;
function setAndFireMockBatteryInfo(charging, chargingTime, dischargingTime, level) {
mockBatteryInfo = { charging: charging,
chargingTime: chargingTime,
dischargingTime: dischargingTime,
level: level };
testRunner.didChangeBatteryStatus(charging, chargingTime, dischargingTime, level);
}
// compare obtained battery values with the mock values
function checkBatteryInfo(batteryManager) {
batteryInfo = batteryManager;
shouldBeDefined("batteryInfo");
shouldBeDefined("mockBatteryInfo");
shouldBe('batteryInfo.charging', 'mockBatteryInfo.charging');
shouldBe('batteryInfo.chargingTime', 'mockBatteryInfo.chargingTime');
shouldBe('batteryInfo.dischargingTime', 'mockBatteryInfo.dischargingTime');
shouldBe('batteryInfo.level', 'mockBatteryInfo.level');
}
function batteryStatusFailure() {
testFailed('failed to successfully resolve the promise');
setTimeout(cleanupAndFinish, 0);
}
var battery;
function batteryStatusSuccess(batteryManager) {
battery = batteryManager;
checkBatteryInfo(battery);
battery.addEventListener('levelchange', failAndFinish);
testRunner.setPageVisibility("hidden");
debug("page is hidden");
setAndFireMockBatteryInfo(false, 10, 20, 0.55);
setTimeout(testWithVisiblePage, 100);
}
function testWithVisiblePage() {
battery.removeEventListener('levelchange', failAndFinish);
battery.addEventListener('levelchange', onLevelChange);
testRunner.setPageVisibility("visible");
debug("page is visible");
setAndFireMockBatteryInfo(false, 10, 20, 0.6);
}
function onLevelChange() {
checkBatteryInfo(battery);
setTimeout(cleanupAndFinish, 0);
}
function cleanupAndFinish() {
// stops updating battery and clears current battery status.
window.testRunner.setPageVisibility("hidden");
finishJSTest();
}
function failAndFinish() {
testFailed('received event while the page was hidden');
setTimeout(cleanupAndFinish, 0);
}
debug("page is visible");
navigator.getBattery().then(batteryStatusSuccess, batteryStatusFailure);
setAndFireMockBatteryInfo(false, 10, 20, 0.5);
</script>
</body>
</html>
Test promise resolution and event listeners callbacks.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
batteryStatusSuccess invoked
PASS batteryInfo is defined.
PASS mockBatteryInfo is defined.
PASS batteryInfo.charging is mockBatteryInfo.charging
PASS batteryInfo.chargingTime is mockBatteryInfo.chargingTime
PASS batteryInfo.dischargingTime is mockBatteryInfo.dischargingTime
PASS batteryInfo.level is mockBatteryInfo.level
chargingchange invoked
PASS batteryInfo is defined.
PASS mockBatteryInfo is defined.
PASS batteryInfo.charging is mockBatteryInfo.charging
PASS batteryInfo.chargingTime is mockBatteryInfo.chargingTime
PASS batteryInfo.dischargingTime is mockBatteryInfo.dischargingTime
PASS batteryInfo.level is mockBatteryInfo.level
chargingtimechange invoked
PASS batteryInfo is defined.
PASS mockBatteryInfo is defined.
PASS batteryInfo.charging is mockBatteryInfo.charging
PASS batteryInfo.chargingTime is mockBatteryInfo.chargingTime
PASS batteryInfo.dischargingTime is mockBatteryInfo.dischargingTime
PASS batteryInfo.level is mockBatteryInfo.level
dischargingtimechange invoked
PASS batteryInfo is defined.
PASS mockBatteryInfo is defined.
PASS batteryInfo.charging is mockBatteryInfo.charging
PASS batteryInfo.chargingTime is mockBatteryInfo.chargingTime
PASS batteryInfo.dischargingTime is mockBatteryInfo.dischargingTime
PASS batteryInfo.level is mockBatteryInfo.level
levelchange invoked
PASS batteryInfo is defined.
PASS mockBatteryInfo is defined.
PASS batteryInfo.charging is mockBatteryInfo.charging
PASS batteryInfo.chargingTime is mockBatteryInfo.chargingTime
PASS batteryInfo.dischargingTime is mockBatteryInfo.dischargingTime
PASS batteryInfo.level is mockBatteryInfo.level
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE html>
<html>
<body>
<script src="../resources/js-test.js"></script>
<script>
description("Test promise resolution and event listeners callbacks.");
if (!window.testRunner)
debug('This test cannot be run without the TestRunner');
jsTestIsAsync = true;
var mockBatteryInfo;
function setAndFireMockBatteryInfo(charging, chargingTime, dischargingTime, level) {
mockBatteryInfo = { charging: charging,
chargingTime: chargingTime,
dischargingTime: dischargingTime,
level: level };
testRunner.didChangeBatteryStatus(charging, chargingTime, dischargingTime, level);
}
// compare obtained battery values with the mock values
function checkBatteryInfo(batteryManager) {
batteryInfo = batteryManager;
shouldBeDefined("batteryInfo");
shouldBeDefined("mockBatteryInfo");
shouldBe('batteryInfo.charging', 'mockBatteryInfo.charging');
shouldBe('batteryInfo.chargingTime', 'mockBatteryInfo.chargingTime');
shouldBe('batteryInfo.dischargingTime', 'mockBatteryInfo.dischargingTime');
shouldBe('batteryInfo.level', 'mockBatteryInfo.level');
}
var battery;
function batteryStatusSuccess(batteryManager) {
debug('batteryStatusSuccess invoked');
battery = batteryManager;
checkBatteryInfo(battery);
battery.addEventListener('chargingchange', onChargingChange);
battery.addEventListener('dischargingtimechange', onDischargingTimeChange);
battery.addEventListener('chargingtimechange', onChargingTimeChange);
battery.addEventListener('levelchange', onLevelChange);
setAndFireMockBatteryInfo(true, 11, 22, 0.6);
}
var chargingChanged = 0;
var chargingTimeChanged = 0;
var dischargingTimeChanged = 0;
var levelChanged = 0;
function onChargingChange() {
debug('chargingchange invoked');
if (this !== battery) { testFailed('this !== battery'); }
checkBatteryInfo(this);
chargingChanged++;
finishIfReady();
}
function onChargingTimeChange() {
debug('chargingtimechange invoked');
if (this !== battery) { testFailed('this !== battery'); }
checkBatteryInfo(this);
chargingTimeChanged++;
finishIfReady();
}
function onDischargingTimeChange() {
debug('dischargingtimechange invoked');
if (this !== battery) { testFailed('this !== battery'); }
checkBatteryInfo(this);
dischargingTimeChanged++;
finishIfReady();
}
function onLevelChange() {
debug('levelchange invoked');
if (this !== battery) { testFailed('this !== battery'); }
checkBatteryInfo(this);
levelChanged++;
finishIfReady();
}
function cleanupAndFinish() {
battery.removeEventListener('chargingchange', onChargingChange);
battery.removeEventListener('dischargingtimechange', onDischargingTimeChange);
battery.removeEventListener('chargingtimechange', onChargingTimeChange);
battery.removeEventListener('levelchange', onLevelChange);
// stops updating battery and clears current battery status.
window.testRunner.setPageVisibility("hidden");
finishJSTest();
}
function finishIfReady() {
if (chargingChanged == 1 && chargingTimeChanged == 1 && dischargingTimeChanged == 1 && levelChanged == 1) {
setTimeout(cleanupAndFinish, 0);
}
}
function batteryStatusFailure() {
testFailed('failed to successfully resolve the promise');
setTimeout(cleanupAndFinish, 0);
}
navigator.getBattery().then(batteryStatusSuccess, batteryStatusFailure);
setAndFireMockBatteryInfo(false, 10, 20, 0.5);
</script>
</body>
</html>
This test prints the default battery status values.
Charging Status: Charging
Charging Time: 0
Discharging Time: Infinity
Percentage: 100
<html>
<body>
<p>This test prints the default battery status values.</p>
<p id="p1"></p>
<p id="p2"></p>
<p id="p3"></p>
<p id="p4"></p>
</body>
<script>
if (window.testRunner)
testRunner.dumpAsText();
var battery = navigator.battery;
document.getElementById("p1").innerHTML = "Charging Status: " + (battery.charging ? "Charging" : "Discharging");
document.getElementById("p2").innerHTML = "Charging Time: " + battery.chargingTime;
document.getElementById("p3").innerHTML = "Discharging Time: " + battery.dischargingTime;
document.getElementById("p4").innerHTML = "Percentage: " + battery.level*100;
</script>
</html>
......@@ -42,14 +42,6 @@ PASS window.cached_navigator.productSub is window.navigator.productSub
PASS window.cached_navigator.userAgent is ''
PASS window.cached_navigator.vendor is window.navigator.vendor
PASS window.cached_navigator.vendorSub is ''
FAIL window.cached_navigator_battery.charging should be false. Was true.
PASS window.cached_navigator_battery.chargingTime is 0
FAIL window.cached_navigator_battery.dischargingTime should be 0. Was Infinity.
FAIL window.cached_navigator_battery.level should be 0. Was 1.
PASS window.cached_navigator_battery.onchargingchange is null
PASS window.cached_navigator_battery.onchargingtimechange is null
PASS window.cached_navigator_battery.ondischargingtimechange is null
PASS window.cached_navigator_battery.onlevelchange is null
PASS window.cached_navigator_connection.ontypechange is null
PASS window.cached_navigator_connection.type is window.navigator.connection.type
PASS window.cached_navigator_serviceWorker.controller is null
......
......@@ -42,14 +42,6 @@ PASS window.cached_navigator.productSub is window.navigator.productSub
PASS window.cached_navigator.userAgent is ''
PASS window.cached_navigator.vendor is window.navigator.vendor
PASS window.cached_navigator.vendorSub is ''
FAIL window.cached_navigator_battery.charging should be false. Was true.
PASS window.cached_navigator_battery.chargingTime is 0
FAIL window.cached_navigator_battery.dischargingTime should be 0. Was Infinity.
FAIL window.cached_navigator_battery.level should be 0. Was 1.
PASS window.cached_navigator_battery.onchargingchange is null
PASS window.cached_navigator_battery.onchargingtimechange is null
PASS window.cached_navigator_battery.ondischargingtimechange is null
PASS window.cached_navigator_battery.onlevelchange is null
PASS window.cached_navigator_connection.ontypechange is null
PASS window.cached_navigator_connection.type is window.navigator.connection.type
PASS window.cached_navigator_serviceWorker.controller is null
......
......@@ -42,14 +42,6 @@ PASS window.cached_navigator.productSub is window.navigator.productSub
PASS window.cached_navigator.userAgent is ''
PASS window.cached_navigator.vendor is window.navigator.vendor
PASS window.cached_navigator.vendorSub is ''
FAIL window.cached_navigator_battery.charging should be false. Was true.
PASS window.cached_navigator_battery.chargingTime is 0
FAIL window.cached_navigator_battery.dischargingTime should be 0. Was Infinity.
FAIL window.cached_navigator_battery.level should be 0. Was 1.
PASS window.cached_navigator_battery.onchargingchange is null
PASS window.cached_navigator_battery.onchargingtimechange is null
PASS window.cached_navigator_battery.ondischargingtimechange is null
PASS window.cached_navigator_battery.onlevelchange is null
PASS window.cached_navigator_connection.ontypechange is null
PASS window.cached_navigator_connection.type is window.navigator.connection.type
PASS window.cached_navigator_serviceWorker.controller is null
......
......@@ -41,14 +41,6 @@ PASS oldChildWindow.name is newChildWindow.name
PASS oldChildWindow.navigator.appCodeName is newChildWindow.navigator.appCodeName
PASS oldChildWindow.navigator.appName is newChildWindow.navigator.appName
PASS oldChildWindow.navigator.appVersion is newChildWindow.navigator.appVersion
PASS oldChildWindow.navigator.battery.charging is newChildWindow.navigator.battery.charging
PASS oldChildWindow.navigator.battery.chargingTime is newChildWindow.navigator.battery.chargingTime
PASS oldChildWindow.navigator.battery.dischargingTime is newChildWindow.navigator.battery.dischargingTime
PASS oldChildWindow.navigator.battery.level is newChildWindow.navigator.battery.level
PASS oldChildWindow.navigator.battery.onchargingchange is newChildWindow.navigator.battery.onchargingchange
PASS oldChildWindow.navigator.battery.onchargingtimechange is newChildWindow.navigator.battery.onchargingtimechange
PASS oldChildWindow.navigator.battery.ondischargingtimechange is newChildWindow.navigator.battery.ondischargingtimechange
PASS oldChildWindow.navigator.battery.onlevelchange is newChildWindow.navigator.battery.onlevelchange
PASS oldChildWindow.navigator.connection.ontypechange is newChildWindow.navigator.connection.ontypechange
PASS oldChildWindow.navigator.connection.type is newChildWindow.navigator.connection.type
PASS oldChildWindow.navigator.cookieEnabled is newChildWindow.navigator.cookieEnabled
......
......@@ -41,14 +41,6 @@ PASS childWindow.name is ''
PASS childWindow.navigator.appCodeName is window.navigator.appCodeName
PASS childWindow.navigator.appName is window.navigator.appName
PASS childWindow.navigator.appVersion is ''
FAIL childWindow.navigator.battery.charging should be false. Threw exception TypeError: Cannot read property 'charging' of null
FAIL childWindow.navigator.battery.chargingTime should be 0. Threw exception TypeError: Cannot read property 'chargingTime' of null
FAIL childWindow.navigator.battery.dischargingTime should be 0. Threw exception TypeError: Cannot read property 'dischargingTime' of null
FAIL childWindow.navigator.battery.level should be 0. Threw exception TypeError: Cannot read property 'level' of null
FAIL childWindow.navigator.battery.onchargingchange should be null. Threw exception TypeError: Cannot read property 'onchargingchange' of null
FAIL childWindow.navigator.battery.onchargingtimechange should be null. Threw exception TypeError: Cannot read property 'onchargingtimechange' of null
FAIL childWindow.navigator.battery.ondischargingtimechange should be null. Threw exception TypeError: Cannot read property 'ondischargingtimechange' of null
FAIL childWindow.navigator.battery.onlevelchange should be null. Threw exception TypeError: Cannot read property 'onlevelchange' of null
FAIL childWindow.navigator.connection.ontypechange should be null. Threw exception TypeError: Cannot read property 'ontypechange' of null
FAIL childWindow.navigator.connection.type should be other. Threw exception TypeError: Cannot read property 'type' of null
PASS childWindow.navigator.cookieEnabled is false
......
......@@ -40,14 +40,6 @@ PASS childWindow.name is ''
PASS childWindow.navigator.appCodeName is window.navigator.appCodeName
PASS childWindow.navigator.appName is window.navigator.appName
PASS childWindow.navigator.appVersion is ''
FAIL childWindow.navigator.battery.charging should be false. Was true.
PASS childWindow.navigator.battery.chargingTime is 0
FAIL childWindow.navigator.battery.dischargingTime should be 0. Was Infinity.
FAIL childWindow.navigator.battery.level should be 0. Was 1.
PASS childWindow.navigator.battery.onchargingchange is null
PASS childWindow.navigator.battery.onchargingtimechange is null
PASS childWindow.navigator.battery.ondischargingtimechange is null
PASS childWindow.navigator.battery.onlevelchange is null
PASS childWindow.navigator.connection.ontypechange is null
PASS childWindow.navigator.connection.type is window.navigator.connection.type
PASS childWindow.navigator.cookieEnabled is false
......
......@@ -27,9 +27,28 @@ BatteryManager::BatteryManager(ExecutionContext* context)
: ActiveDOMObject(context)
, DeviceEventControllerBase(toDocument(context)->page())
, m_batteryStatus(BatteryStatus::create())
, m_state(NotStarted)
{
m_hasEventListener = true;
startUpdating();
}
ScriptPromise BatteryManager::startRequest(ScriptState* scriptState)
{
if (m_state == Pending)
return m_resolver->promise();
m_resolver = ScriptPromiseResolverWithContext::create(scriptState);
ScriptPromise promise = m_resolver->promise();
if (m_state == Resolved) {
// FIXME: Consider returning the same promise in this case. See crbug.com/385025.
m_resolver->resolve(this);
} else if (m_state == NotStarted) {
m_state = Pending;
m_hasEventListener = true;
startUpdating();
}
return promise;
}
bool BatteryManager::charging()
......@@ -55,6 +74,7 @@ double BatteryManager::level()
void BatteryManager::didUpdateData()
{
ASSERT(RuntimeEnabledFeatures::batteryStatusEnabled());
ASSERT(m_state != NotStarted);
RefPtr<BatteryStatus> oldStatus = m_batteryStatus;
m_batteryStatus = BatteryDispatcher::instance().latestData();
......@@ -62,6 +82,13 @@ void BatteryManager::didUpdateData()
// BatteryDispatcher also holds a reference to m_batteryStatus.
ASSERT(m_batteryStatus->refCount() > 1);
if (m_state == Pending) {
ASSERT(m_resolver);
m_state = Resolved;
m_resolver->resolve(this);
return;
}
Document* document = toDocument(executionContext());
if (document->activeDOMObjectsAreSuspended() || document->activeDOMObjectsAreStopped())
return;
......
......@@ -5,6 +5,8 @@
#ifndef BatteryManager_h
#define BatteryManager_h
#include "bindings/v8/ScriptPromise.h"
#include "bindings/v8/ScriptPromiseResolverWithContext.h"
#include "core/dom/ContextLifecycleObserver.h"
#include "core/dom/Document.h"
#include "core/frame/DeviceEventControllerBase.h"
......@@ -14,7 +16,6 @@
namespace WebCore {
class BatteryStatus;
class Navigator;
class BatteryManager FINAL : public RefCountedWillBeRefCountedGarbageCollected<BatteryManager>, public ActiveDOMObject, public DeviceEventControllerBase, public EventTargetWithInlineData {
REFCOUNTED_EVENT_TARGET(BatteryManager);
......@@ -23,6 +24,9 @@ public:
virtual ~BatteryManager();
static PassRefPtrWillBeRawPtr<BatteryManager> create(ExecutionContext*);
// Returns a promise object that will be resolved with this BatteryManager.
ScriptPromise startRequest(ScriptState*);
// EventTarget implementation.
virtual const WTF::AtomicString& interfaceName() const OVERRIDE { return EventTargetNames::BatteryManager; }
virtual ExecutionContext* executionContext() const OVERRIDE { return ContextLifecycleObserver::executionContext(); }
......@@ -50,9 +54,17 @@ public:
virtual void stop() OVERRIDE;
private:
enum State {
NotStarted,
Pending,
Resolved,
};
explicit BatteryManager(ExecutionContext*);
RefPtr<ScriptPromiseResolverWithContext> m_resolver;
RefPtr<BatteryStatus> m_batteryStatus;
State m_state;
};
}
......
......@@ -18,16 +18,17 @@ NavigatorBattery::~NavigatorBattery()
{
}
BatteryManager* NavigatorBattery::battery(Navigator& navigator)
ScriptPromise NavigatorBattery::getBattery(ScriptState* scriptState, Navigator& navigator)
{
return NavigatorBattery::from(navigator).batteryManager(navigator);
return NavigatorBattery::from(navigator).getBattery(scriptState);
}
BatteryManager* NavigatorBattery::batteryManager(Navigator& navigator)
ScriptPromise NavigatorBattery::getBattery(ScriptState* scriptState)
{
if (!m_batteryManager && navigator.frame())
m_batteryManager = BatteryManager::create(navigator.frame()->document());
return m_batteryManager.get();
if (!m_batteryManager)
m_batteryManager = BatteryManager::create(scriptState->executionContext());
return m_batteryManager->startRequest(scriptState);
}
const char* NavigatorBattery::supplementName()
......
......@@ -5,6 +5,7 @@
#ifndef NavigatorBattery_h
#define NavigatorBattery_h
#include "bindings/v8/ScriptPromise.h"
#include "core/frame/Navigator.h"
#include "platform/Supplementable.h"
#include "platform/heap/Handle.h"
......@@ -21,8 +22,8 @@ public:
static NavigatorBattery& from(Navigator&);
static BatteryManager* battery(Navigator&);
BatteryManager* batteryManager(Navigator&);
static ScriptPromise getBattery(ScriptState*, Navigator&);
ScriptPromise getBattery(ScriptState*);
void trace(Visitor*);
......
......@@ -5,6 +5,6 @@
[
RuntimeEnabled=BatteryStatus,
] partial interface Navigator {
readonly attribute BatteryManager battery;
[CallWith=ScriptState] Promise getBattery();
};
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