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 <utility>
6
7 #include "content/browser/idle/idle_manager.h"
8
9 #include "base/bind.h"
10 #include "base/callback_helpers.h"
11 #include "content/browser/idle/idle_monitor.h"
12 #include "content/public/browser/permission_controller.h"
13 #include "content/public/browser/permission_type.h"
14 #include "ui/base/idle/idle.h"
15
16 namespace content {
17
18 namespace {
19
20 constexpr base::TimeDelta kPollInterval = base::TimeDelta::FromSeconds(1);
21
22 constexpr base::TimeDelta kMinimumThreshold = base::TimeDelta::FromSeconds(60);
23
24 // Default provider implementation. Everything is delegated to
25 // ui::CalculateIdleState, ui::CalculateIdleTime, and
26 // ui::CheckIdleStateIsLocked.
27 class DefaultIdleProvider : public IdleManager::IdleTimeProvider {
28 public:
29 DefaultIdleProvider() = default;
30 ~DefaultIdleProvider() override = default;
31
CalculateIdleState(base::TimeDelta idle_threshold)32 ui::IdleState CalculateIdleState(base::TimeDelta idle_threshold) override {
33 return ui::CalculateIdleState(idle_threshold.InSeconds());
34 }
35
CalculateIdleTime()36 base::TimeDelta CalculateIdleTime() override {
37 return base::TimeDelta::FromSeconds(ui::CalculateIdleTime());
38 }
39
CheckIdleStateIsLocked()40 bool CheckIdleStateIsLocked() override {
41 return ui::CheckIdleStateIsLocked();
42 }
43 };
44
IdleTimeToIdleState(bool locked,base::TimeDelta idle_time,base::TimeDelta idle_threshold)45 blink::mojom::IdleStatePtr IdleTimeToIdleState(bool locked,
46 base::TimeDelta idle_time,
47 base::TimeDelta idle_threshold) {
48 blink::mojom::UserIdleState user;
49 if (idle_time >= idle_threshold)
50 user = blink::mojom::UserIdleState::kIdle;
51 else
52 user = blink::mojom::UserIdleState::kActive;
53
54 blink::mojom::ScreenIdleState screen;
55 if (locked)
56 screen = blink::mojom::ScreenIdleState::kLocked;
57 else
58 screen = blink::mojom::ScreenIdleState::kUnlocked;
59
60 return blink::mojom::IdleState::New(user, screen);
61 }
62
63 } // namespace
64
IdleManager()65 IdleManager::IdleManager() : idle_time_provider_(new DefaultIdleProvider()) {}
66
~IdleManager()67 IdleManager::~IdleManager() {
68 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
69
70 while (!monitors_.empty()) {
71 IdleMonitor* monitor = monitors_.head()->value();
72 monitor->RemoveFromList();
73 delete monitor;
74 }
75 }
76
CreateService(mojo::PendingReceiver<blink::mojom::IdleManager> receiver)77 void IdleManager::CreateService(
78 mojo::PendingReceiver<blink::mojom::IdleManager> receiver) {
79 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
80
81 receivers_.Add(this, std::move(receiver));
82 }
83
AddMonitor(base::TimeDelta threshold,mojo::PendingRemote<blink::mojom::IdleMonitor> monitor_remote,AddMonitorCallback callback)84 void IdleManager::AddMonitor(
85 base::TimeDelta threshold,
86 mojo::PendingRemote<blink::mojom::IdleMonitor> monitor_remote,
87 AddMonitorCallback callback) {
88 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
89 if (threshold < kMinimumThreshold) {
90 receivers_.ReportBadMessage("Minimum threshold is 60 seconds.");
91 return;
92 }
93
94 auto monitor = std::make_unique<IdleMonitor>(
95 std::move(monitor_remote), CheckIdleState(threshold), threshold);
96
97 // This unretained reference is safe because IdleManager owns all IdleMonitor
98 // instances.
99 monitor->SetErrorHandler(
100 base::BindOnce(&IdleManager::RemoveMonitor, base::Unretained(this)));
101
102 monitors_.Append(monitor.release());
103
104 StartPolling();
105
106 std::move(callback).Run(CheckIdleState(threshold));
107 }
108
RemoveMonitor(IdleMonitor * monitor)109 void IdleManager::RemoveMonitor(IdleMonitor* monitor) {
110 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
111
112 monitor->RemoveFromList();
113 delete monitor;
114
115 if (monitors_.empty()) {
116 StopPolling();
117 }
118 }
119
SetIdleTimeProviderForTest(std::unique_ptr<IdleTimeProvider> idle_time_provider)120 void IdleManager::SetIdleTimeProviderForTest(
121 std::unique_ptr<IdleTimeProvider> idle_time_provider) {
122 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
123 idle_time_provider_ = std::move(idle_time_provider);
124 }
125
IsPollingForTest()126 bool IdleManager::IsPollingForTest() {
127 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
128 return poll_timer_.IsRunning();
129 }
130
StartPolling()131 void IdleManager::StartPolling() {
132 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
133 if (!poll_timer_.IsRunning()) {
134 poll_timer_.Start(FROM_HERE, kPollInterval,
135 base::BindRepeating(&IdleManager::UpdateIdleState,
136 base::Unretained(this)));
137 }
138 }
139
StopPolling()140 void IdleManager::StopPolling() {
141 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
142 poll_timer_.Stop();
143 }
144
CheckIdleState(base::TimeDelta threshold)145 blink::mojom::IdleStatePtr IdleManager::CheckIdleState(
146 base::TimeDelta threshold) {
147 base::TimeDelta idle_time = idle_time_provider_->CalculateIdleTime();
148 bool locked = idle_time_provider_->CheckIdleStateIsLocked();
149
150 return IdleTimeToIdleState(locked, idle_time, threshold);
151 }
152
UpdateIdleState()153 void IdleManager::UpdateIdleState() {
154 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
155
156 for (auto* node = monitors_.head(); node != monitors_.end();
157 node = node->next()) {
158 IdleMonitor* monitor = node->value();
159 monitor->SetLastState(CheckIdleState(monitor->threshold()));
160 }
161 }
162
163 } // namespace content
164