blob: b259618d599f4f3f8f7a62a278e93af229b0eba9 [file]
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/device/generic_sensor/sensor_impl.h"
#include <utility>
#include "base/functional/bind.h"
#include "services/device/generic_sensor/sensor_provider_impl.h"
namespace device {
// Receives suspend/resume control messages from the browser process via Mojo
// and forwards them to the associated SensorImpl. This allows the browser
// to supervise the sensor session (e.g. suspending it when the page is
// backgrounded or in BFCache).
class SensorImpl::SensorClientControllerImpl
: public mojom::SensorClientController {
public:
SensorClientControllerImpl(
SensorImpl* sensor,
mojo::PendingReceiver<mojom::SensorClientController> receiver)
: sensor_(sensor), receiver_(this, std::move(receiver)) {
// A disconnect on the control pipe indicates that the browser/controller is
// revoking access to the sensor (e.g., when the user revokes sensor
// permissions in site settings while active, or when the frame is
// destroyed). Removing the sensor tears down the renderer-facing Sensor and
// SensorClient pipes.
receiver_.set_disconnect_handler(base::BindOnce(
&SensorClientControllerImpl::OnDisconnect, base::Unretained(this)));
}
void Suspend() override { sensor_->OnControllerSuspend(); }
void Resume() override { sensor_->OnControllerResume(); }
private:
void OnDisconnect() { sensor_->OnControllerDisconnect(); }
raw_ptr<SensorImpl> sensor_;
mojo::Receiver<mojom::SensorClientController> receiver_;
};
SensorImpl::SensorImpl(
scoped_refptr<PlatformSensor> sensor,
mojo::PendingReceiver<mojom::SensorClientController> controller,
bool initially_suspended,
SensorProviderImpl* provider)
: sensor_(std::move(sensor)),
reading_notification_enabled_(true),
client_suspended_(false),
controller_suspended_(initially_suspended),
provider_(provider) {
sensor_->AddClient(this);
if (controller.is_valid()) {
client_controller_ = std::make_unique<SensorClientControllerImpl>(
this, std::move(controller));
}
}
SensorImpl::~SensorImpl() {
sensor_->RemoveClient(this);
}
mojo::PendingReceiver<mojom::SensorClient> SensorImpl::GetClient() {
return client_.BindNewPipeAndPassReceiver();
}
void SensorImpl::AddConfiguration(
const PlatformSensorConfiguration& configuration,
AddConfigurationCallback callback) {
// TODO(Mikhail): To avoid overflowing browser by repeated AddConfigs
// (maybe limit the number of configs per client).
std::move(callback).Run(sensor_->StartListening(this, configuration));
}
void SensorImpl::GetDefaultConfiguration(
GetDefaultConfigurationCallback callback) {
std::move(callback).Run(sensor_->GetDefaultConfiguration());
}
void SensorImpl::RemoveConfiguration(
const PlatformSensorConfiguration& configuration) {
sensor_->StopListening(this, configuration);
}
void SensorImpl::Suspend() {
if (client_suspended_) {
return;
}
client_suspended_ = true;
sensor_->UpdateSensor();
}
void SensorImpl::Resume() {
if (!client_suspended_) {
return;
}
client_suspended_ = false;
sensor_->UpdateSensor();
}
void SensorImpl::OnControllerSuspend() {
if (controller_suspended_) {
return;
}
controller_suspended_ = true;
sensor_->UpdateSensor();
}
void SensorImpl::OnControllerResume() {
if (!controller_suspended_) {
return;
}
controller_suspended_ = false;
sensor_->UpdateSensor();
}
void SensorImpl::OnControllerDisconnect() {
provider_->RemoveSensor(this);
}
void SensorImpl::ConfigureReadingChangeNotifications(bool enabled) {
reading_notification_enabled_ = enabled;
}
void SensorImpl::OnSensorReadingChanged(mojom::SensorType type) {
DCHECK(!IsSuspended());
if (client_ && reading_notification_enabled_ &&
sensor_->GetReportingMode() == mojom::ReportingMode::ON_CHANGE) {
client_->SensorReadingChanged();
}
}
void SensorImpl::OnSensorError() {
if (client_)
client_->RaiseError();
}
bool SensorImpl::IsSuspended() {
return client_suspended_ || controller_suspended_;
}
} // namespace device