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