1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "third_party/blink/renderer/modules/sensor/sensor_proxy_impl.h"
6 
7 #include "services/device/public/cpp/generic_sensor/sensor_traits.h"
8 #include "third_party/blink/public/platform/platform.h"
9 #include "third_party/blink/public/platform/task_type.h"
10 #include "third_party/blink/renderer/modules/sensor/sensor_provider_proxy.h"
11 #include "third_party/blink/renderer/modules/sensor/sensor_reading_remapper.h"
12 #include "third_party/blink/renderer/platform/mojo/mojo_helper.h"
13 
14 using device::mojom::blink::SensorCreationResult;
15 
16 namespace blink {
17 
SensorProxyImpl(device::mojom::blink::SensorType sensor_type,SensorProviderProxy * provider,Page * page)18 SensorProxyImpl::SensorProxyImpl(device::mojom::blink::SensorType sensor_type,
19                                  SensorProviderProxy* provider,
20                                  Page* page)
21     : SensorProxy(sensor_type, provider, page),
22       sensor_remote_(provider->GetSupplementable()->GetExecutionContext()),
23       client_receiver_(this,
24                        provider->GetSupplementable()->GetExecutionContext()),
25       task_runner_(
26           provider->GetSupplementable()->GetTaskRunner(TaskType::kSensor)),
27       polling_timer_(
28           provider->GetSupplementable()->GetTaskRunner(TaskType::kSensor),
29           this,
30           &SensorProxyImpl::OnPollingTimer) {}
31 
~SensorProxyImpl()32 SensorProxyImpl::~SensorProxyImpl() {}
33 
Trace(Visitor * visitor) const34 void SensorProxyImpl::Trace(Visitor* visitor) const {
35   visitor->Trace(sensor_remote_);
36   visitor->Trace(client_receiver_);
37   SensorProxy::Trace(visitor);
38 }
39 
Initialize()40 void SensorProxyImpl::Initialize() {
41   if (state_ != kUninitialized)
42     return;
43 
44   if (!sensor_provider_proxy()) {
45     HandleSensorError();
46     return;
47   }
48 
49   state_ = kInitializing;
50   sensor_provider_proxy()->GetSensor(
51       type_,
52       WTF::Bind(&SensorProxyImpl::OnSensorCreated, WrapWeakPersistent(this)));
53 }
54 
AddConfiguration(device::mojom::blink::SensorConfigurationPtr configuration,base::OnceCallback<void (bool)> callback)55 void SensorProxyImpl::AddConfiguration(
56     device::mojom::blink::SensorConfigurationPtr configuration,
57     base::OnceCallback<void(bool)> callback) {
58   DCHECK(IsInitialized());
59   AddActiveFrequency(configuration->frequency);
60   sensor_remote_->AddConfiguration(std::move(configuration),
61                                    std::move(callback));
62 }
63 
RemoveConfiguration(device::mojom::blink::SensorConfigurationPtr configuration)64 void SensorProxyImpl::RemoveConfiguration(
65     device::mojom::blink::SensorConfigurationPtr configuration) {
66   DCHECK(IsInitialized());
67   RemoveActiveFrequency(configuration->frequency);
68   if (sensor_remote_.is_bound())
69     sensor_remote_->RemoveConfiguration(std::move(configuration));
70 }
71 
GetDefaultFrequency() const72 double SensorProxyImpl::GetDefaultFrequency() const {
73   DCHECK(IsInitialized());
74   return default_frequency_;
75 }
76 
GetFrequencyLimits() const77 std::pair<double, double> SensorProxyImpl::GetFrequencyLimits() const {
78   DCHECK(IsInitialized());
79   return frequency_limits_;
80 }
81 
Suspend()82 void SensorProxyImpl::Suspend() {
83   if (suspended_ || !sensor_remote_.is_bound())
84     return;
85 
86   sensor_remote_->Suspend();
87   suspended_ = true;
88   UpdatePollingStatus();
89 }
90 
Resume()91 void SensorProxyImpl::Resume() {
92   if (!suspended_ || !sensor_remote_.is_bound())
93     return;
94 
95   sensor_remote_->Resume();
96   suspended_ = false;
97   UpdatePollingStatus();
98 }
99 
UpdateSensorReading()100 void SensorProxyImpl::UpdateSensorReading() {
101   DCHECK(ShouldProcessReadings());
102   DCHECK(shared_buffer_reader_);
103 
104   // Try to read the latest value from shared memory. Failure should not be
105   // fatal because we only retry a finite number of times.
106   device::SensorReading reading_data;
107   if (!shared_buffer_reader_->GetReading(&reading_data))
108     return;
109 
110   double latest_timestamp = reading_data.timestamp();
111   if (reading_.timestamp() != latest_timestamp &&
112       latest_timestamp != 0.0)  // The shared buffer is zeroed when
113                                 // sensor is stopped, we skip this
114                                 // reading.
115   {
116     DCHECK_GT(latest_timestamp, reading_.timestamp())
117         << "Timestamps must increase monotonically";
118     reading_ = reading_data;
119     for (Observer* observer : observers_)
120       observer->OnSensorReadingChanged();
121   }
122 }
123 
RaiseError()124 void SensorProxyImpl::RaiseError() {
125   HandleSensorError();
126 }
127 
SensorReadingChanged()128 void SensorProxyImpl::SensorReadingChanged() {
129   DCHECK_EQ(device::mojom::blink::ReportingMode::ON_CHANGE, mode_);
130   if (ShouldProcessReadings())
131     UpdateSensorReading();
132 }
133 
ReportError(DOMExceptionCode code,const String & message)134 void SensorProxyImpl::ReportError(DOMExceptionCode code,
135                                   const String& message) {
136   state_ = kUninitialized;
137   active_frequencies_.clear();
138   reading_ = device::SensorReading();
139   UpdatePollingStatus();
140 
141   // The m_sensor.reset() will release all callbacks and its bound parameters,
142   // therefore, handleSensorError accepts messages by value.
143   sensor_remote_.reset();
144   shared_buffer_reader_.reset();
145   default_frequency_ = 0.0;
146   frequency_limits_ = {0.0, 0.0};
147   client_receiver_.reset();
148 
149   SensorProxy::ReportError(code, message);
150 }
151 
HandleSensorError(SensorCreationResult error)152 void SensorProxyImpl::HandleSensorError(SensorCreationResult error) {
153   if (error == SensorCreationResult::ERROR_NOT_ALLOWED) {
154     String description = "Permissions to access sensor are not granted";
155     ReportError(DOMExceptionCode::kNotAllowedError, std::move(description));
156   } else {
157     ReportError(DOMExceptionCode::kNotReadableError, kDefaultErrorDescription);
158   }
159 }
160 
OnSensorCreated(SensorCreationResult result,device::mojom::blink::SensorInitParamsPtr params)161 void SensorProxyImpl::OnSensorCreated(
162     SensorCreationResult result,
163     device::mojom::blink::SensorInitParamsPtr params) {
164   DCHECK_EQ(kInitializing, state_);
165   if (!params) {
166     DCHECK_NE(SensorCreationResult::SUCCESS, result);
167     HandleSensorError(result);
168     return;
169   }
170 
171   DCHECK_EQ(SensorCreationResult::SUCCESS, result);
172 
173   mode_ = params->mode;
174   if (!params->default_configuration) {
175     HandleSensorError();
176     return;
177   }
178 
179   default_frequency_ = params->default_configuration->frequency;
180   DCHECK_GT(default_frequency_, 0.0);
181 
182   sensor_remote_.Bind(std::move(params->sensor), task_runner_);
183   client_receiver_.Bind(std::move(params->client_receiver), task_runner_);
184 
185   shared_buffer_reader_ = device::SensorReadingSharedBufferReader::Create(
186       std::move(params->memory), params->buffer_offset);
187   if (!shared_buffer_reader_) {
188     HandleSensorError();
189     return;
190   }
191 
192   shared_buffer_reader_->GetReading(&reading_);
193 
194   frequency_limits_.first = params->minimum_frequency;
195   frequency_limits_.second = params->maximum_frequency;
196 
197   DCHECK_GT(frequency_limits_.first, 0.0);
198   DCHECK_GE(frequency_limits_.second, frequency_limits_.first);
199   DCHECK_GE(device::GetSensorMaxAllowedFrequency(type_),
200             frequency_limits_.second);
201 
202   auto error_callback =
203       WTF::Bind(&SensorProxyImpl::HandleSensorError, WrapWeakPersistent(this),
204                 SensorCreationResult::ERROR_NOT_AVAILABLE);
205   sensor_remote_.set_disconnect_handler(std::move(error_callback));
206 
207   state_ = kInitialized;
208 
209   UpdateSuspendedStatus();
210 
211   for (Observer* observer : observers_)
212     observer->OnSensorInitialized();
213 }
214 
OnPollingTimer(TimerBase *)215 void SensorProxyImpl::OnPollingTimer(TimerBase*) {
216   UpdateSensorReading();
217 }
218 
ShouldProcessReadings() const219 bool SensorProxyImpl::ShouldProcessReadings() const {
220   return IsInitialized() && !suspended_ && !active_frequencies_.IsEmpty();
221 }
222 
UpdatePollingStatus()223 void SensorProxyImpl::UpdatePollingStatus() {
224   if (mode_ != device::mojom::blink::ReportingMode::CONTINUOUS)
225     return;
226 
227   if (ShouldProcessReadings()) {
228     // TODO(crbug/721297) : We need to find out an algorithm for resulting
229     // polling frequency.
230     polling_timer_.StartRepeating(
231         base::TimeDelta::FromSecondsD(1 / active_frequencies_.back()),
232         FROM_HERE);
233   } else {
234     polling_timer_.Stop();
235   }
236 }
237 
RemoveActiveFrequency(double frequency)238 void SensorProxyImpl::RemoveActiveFrequency(double frequency) {
239   // Can use binary search as active_frequencies_ is sorted.
240   Vector<double>::iterator it = std::lower_bound(
241       active_frequencies_.begin(), active_frequencies_.end(), frequency);
242   if (it == active_frequencies_.end() || *it != frequency) {
243     NOTREACHED() << "Attempted to remove active frequency which is not present "
244                     "in the list";
245     return;
246   }
247 
248   active_frequencies_.erase(it);
249   UpdatePollingStatus();
250 
251   if (active_frequencies_.IsEmpty())
252     reading_ = device::SensorReading();
253 }
254 
AddActiveFrequency(double frequency)255 void SensorProxyImpl::AddActiveFrequency(double frequency) {
256   Vector<double>::iterator it = std::lower_bound(
257       active_frequencies_.begin(), active_frequencies_.end(), frequency);
258   if (it == active_frequencies_.end()) {
259     active_frequencies_.push_back(frequency);
260   } else {
261     active_frequencies_.insert(
262         static_cast<wtf_size_t>(std::distance(active_frequencies_.begin(), it)),
263         frequency);
264   }
265   UpdatePollingStatus();
266 }
267 
268 }  // namespace blink
269