blob: 531c3b8fe0542b280806b82658acc0ff888f6c5b [file] [log] [blame]
'use strict';
var GenericSensorTest = (() => {
// Class that mocks Sensor interface defined in
// https://cs.chromium.org/chromium/src/services/device/public/mojom/sensor.mojom
class MockSensor {
constructor(sensorRequest, handle, offset, size, reportingMode) {
this.client_ = null;
this.reportingMode_ = reportingMode;
this.sensorReadingTimerId_ = null;
this.requestedFrequencies_ = [];
let rv = handle.mapBuffer(offset, size);
assert_equals(rv.result, Mojo.RESULT_OK, "Failed to map shared buffer");
this.buffer_ = new Float64Array(rv.buffer);
this.buffer_.fill(0);
this.binding_ = new mojo.Binding(device.mojom.Sensor, this,
sensorRequest);
this.binding_.setConnectionErrorHandler(() => {
this.reset();
});
}
getDefaultConfiguration() {
return Promise.resolve({frequency: 5});
}
addConfiguration(configuration) {
assert_not_equals(configuration, null, "Invalid sensor configuration.");
this.requestedFrequencies_.push(configuration.frequency);
// Sort using descending order.
this.requestedFrequencies_.sort(
(first, second) => { return second - first });
this.startReading();
return Promise.resolve({success: true});
}
removeConfiguration(configuration) {
let index = this.requestedFrequencies_.indexOf(configuration.frequency);
if (index == -1)
return;
this.requestedFrequencies_.splice(index, 1);
if (this.isReading) {
this.stopReading();
if (this.requestedFrequencies_.length !== 0)
this.startReading();
}
}
suspend() {
this.stopReading();
}
resume() {
this.startReading();
}
reset() {
this.stopReading();
this.requestedFrequencies_ = [];
this.buffer_.fill(0);
this.binding_.close();
}
startReading() {
if (this.isReading) {
console.warn("Sensor reading is already started.");
return;
}
if (this.requestedFrequencies_.length == 0) {
console.warn("Sensor reading cannot be started as" +
"there are no configurations added.");
return;
}
const maxFrequencyHz = this.requestedFrequencies_[0];
const timeoutMs = (1 / maxFrequencyHz) * 1000;
this.sensorReadingTimerId_ = window.setInterval(() => {
// For all tests sensor reading should have monotonically
// increasing timestamp in seconds.
this.buffer_[1] = window.performance.now() * 0.001;
if (this.reportingMode_ === device.mojom.ReportingMode.ON_CHANGE) {
this.client_.sensorReadingChanged();
}
}, timeoutMs);
}
stopReading() {
if (this.isReading) {
window.clearInterval(this.sensorReadingTimerId_);
this.sensorReadingTimerId_ = null;
}
}
get isReading() {
this.sensorReadingTimerId_ !== null;
}
}
// Class that mocks SensorProvider interface defined in
// https://cs.chromium.org/chromium/src/services/device/public/mojom/sensor_provider.mojom
class MockSensorProvider {
constructor() {
this.readingSizeInBytes_ =
device.mojom.SensorInitParams.kReadBufferSizeForTests;
this.sharedBufferSizeInBytes_ = this.readingSizeInBytes_ *
(device.mojom.SensorType.MAX_VALUE + 1);
let rv = Mojo.createSharedBuffer(this.sharedBufferSizeInBytes_);
assert_equals(rv.result, Mojo.RESULT_OK, "Failed to create buffer");
this.sharedBufferHandle_ = rv.handle;
this.activeSensor_ = null;
this.isContinuous_ = false;
this.binding_ = new mojo.Binding(device.mojom.SensorProvider, this);
this.interceptor_ = new MojoInterfaceInterceptor(
device.mojom.SensorProvider.name);
this.interceptor_.oninterfacerequest = e => {
this.binding_.bind(e.handle);
this.binding_.setConnectionErrorHandler(() => {
console.error("Mojo connection error");
this.reset();
});
};
this.interceptor_.start();
}
async getSensor(type) {
const offset = type * this.readingSizeInBytes_;
const reportingMode = device.mojom.ReportingMode.ON_CHANGE;
let sensorPtr = new device.mojom.SensorPtr();
if (this.activeSensor_ == null) {
let mockSensor = new MockSensor(
mojo.makeRequest(sensorPtr), this.sharedBufferHandle_, offset,
this.readingSizeInBytes_, reportingMode);
this.activeSensor_ = mockSensor;
this.activeSensor_.client_ = new device.mojom.SensorClientPtr();
}
let rv = this.sharedBufferHandle_.duplicateBufferHandle();
assert_equals(rv.result, Mojo.RESULT_OK);
let maxAllowedFrequencyHz = 60;
if (type == device.mojom.SensorType.AMBIENT_LIGHT ||
type == device.mojom.SensorType.MAGNETOMETER) {
maxAllowedFrequencyHz = 10;
}
let initParams = new device.mojom.SensorInitParams({
sensor: sensorPtr,
clientRequest: mojo.makeRequest(this.activeSensor_.client_),
memory: rv.handle,
bufferOffset: offset,
mode: reportingMode,
defaultConfiguration: {frequency: 5},
minimumFrequency: 1,
maximumFrequency: maxAllowedFrequencyHz
});
return {result: device.mojom.SensorCreationResult.SUCCESS,
initParams: initParams};
}
reset() {
if (this.activeSensor_ !== null) {
this.activeSensor_.reset();
this.activeSensor_ = null;
}
this.binding_.close();
this.interceptor_.stop();
}
}
let testInternal = {
initialized: false,
sensorProvider: null
}
class GenericSensorTestChromium {
constructor() {
Object.freeze(this); // Make it immutable.
}
initialize() {
if (testInternal.initialized)
throw new Error('Call reset() before initialize().');
if (window.testRunner) { // Grant sensor permissions for Chromium testrunner.
['accelerometer', 'gyroscope',
'magnetometer', 'ambient-light-sensor'].forEach((entry) => {
window.testRunner.setPermission(entry, 'granted',
location.origin, location.origin);
});
}
testInternal.sensorProvider = new MockSensorProvider;
testInternal.initialized = true;
}
// Resets state of sensor mocks between test runs.
async reset() {
if (!testInternal.initialized)
throw new Error('Call initialize() before reset().');
testInternal.sensorProvider.reset();
testInternal.sensorProvider = null;
testInternal.initialized = false;
// Wait for an event loop iteration to let any pending mojo commands in
// the sensor provider finish.
await new Promise(resolve => setTimeout(resolve, 0));
}
}
return GenericSensorTestChromium;
})();