1 // Copyright 2016 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.h"
6 
7 #include "third_party/blink/public/common/widget/screen_info.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/core/frame/local_frame.h"
11 #include "third_party/blink/renderer/core/page/chrome_client.h"
12 #include "third_party/blink/renderer/core/page/focus_controller.h"
13 #include "third_party/blink/renderer/core/page/page.h"
14 #include "third_party/blink/renderer/modules/sensor/sensor_provider_proxy.h"
15 #include "third_party/blink/renderer/modules/sensor/sensor_reading_remapper.h"
16 #include "third_party/blink/renderer/platform/web_test_support.h"
17 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
18 
19 namespace blink {
20 
21 const char SensorProxy::kDefaultErrorDescription[] =
22     "Could not connect to a sensor";
23 
SensorProxy(device::mojom::blink::SensorType sensor_type,SensorProviderProxy * provider,Page * page)24 SensorProxy::SensorProxy(device::mojom::blink::SensorType sensor_type,
25                          SensorProviderProxy* provider,
26                          Page* page)
27     : PageVisibilityObserver(page),
28       FocusChangedObserver(page),
29       type_(sensor_type),
30       state_(SensorProxy::kUninitialized),
31       provider_(provider) {}
32 
~SensorProxy()33 SensorProxy::~SensorProxy() {}
34 
Trace(Visitor * visitor) const35 void SensorProxy::Trace(Visitor* visitor) const {
36   visitor->Trace(observers_);
37   visitor->Trace(provider_);
38   PageVisibilityObserver::Trace(visitor);
39   FocusChangedObserver::Trace(visitor);
40 }
41 
AddObserver(Observer * observer)42 void SensorProxy::AddObserver(Observer* observer) {
43   if (!observers_.Contains(observer))
44     observers_.insert(observer);
45 }
46 
RemoveObserver(Observer * observer)47 void SensorProxy::RemoveObserver(Observer* observer) {
48   observers_.erase(observer);
49 }
50 
Detach()51 void SensorProxy::Detach() {
52   if (!detached_) {
53     provider_->RemoveSensorProxy(this);
54     detached_ = true;
55   }
56 }
57 
ReportError(DOMExceptionCode code,const String & message)58 void SensorProxy::ReportError(DOMExceptionCode code, const String& message) {
59   auto copy = observers_;
60   for (Observer* observer : copy) {
61     observer->OnSensorError(code, message, String());
62   }
63 }
64 
65 namespace {
66 
GetScreenOrientationAngle(LocalFrame & frame)67 uint16_t GetScreenOrientationAngle(LocalFrame& frame) {
68   if (WebTestSupport::IsRunningWebTest()) {
69     // Simulate that the device is turned 90 degrees on the right.
70     // 'orientation_angle' must be 270 as per
71     // https://w3c.github.io/screen-orientation/#dfn-update-the-orientation-information.
72     return 270;
73   }
74   return frame.GetChromeClient().GetScreenInfo(frame).orientation_angle;
75 }
76 
77 }  // namespace
78 
GetReading(bool remapped) const79 const device::SensorReading& SensorProxy::GetReading(bool remapped) const {
80   DCHECK(IsInitialized());
81   if (remapped) {
82     if (remapped_reading_.timestamp() != reading_.timestamp()) {
83       remapped_reading_ = reading_;
84       SensorReadingRemapper::RemapToScreenCoords(
85           type_,
86           GetScreenOrientationAngle(
87               *provider_->GetSupplementable()->GetFrame()),
88           &remapped_reading_);
89     }
90     return remapped_reading_;
91   }
92   return reading_;
93 }
94 
PageVisibilityChanged()95 void SensorProxy::PageVisibilityChanged() {
96   UpdateSuspendedStatus();
97 }
98 
FocusedFrameChanged()99 void SensorProxy::FocusedFrameChanged() {
100   UpdateSuspendedStatus();
101 }
102 
UpdateSuspendedStatus()103 void SensorProxy::UpdateSuspendedStatus() {
104   if (!IsInitialized())
105     return;
106 
107   if (ShouldSuspendUpdates())
108     Suspend();
109   else
110     Resume();
111 }
112 
ShouldSuspendUpdates() const113 bool SensorProxy::ShouldSuspendUpdates() const {
114   if (!GetPage()->IsPageVisible())
115     return true;
116 
117   LocalFrame* focused_frame = GetPage()->GetFocusController().FocusedFrame();
118   LocalFrame* this_frame = provider_->GetSupplementable()->GetFrame();
119 
120   if (!focused_frame || !this_frame)
121     return true;
122 
123   if (focused_frame == this_frame)
124     return false;
125 
126   const SecurityOrigin* focused_frame_origin =
127       focused_frame->GetSecurityContext()->GetSecurityOrigin();
128   const SecurityOrigin* this_origin =
129       this_frame->GetSecurityContext()->GetSecurityOrigin();
130 
131   return !focused_frame_origin->CanAccess(this_origin);
132 }
133 
134 }  // namespace blink
135