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