blob: e6f0354fe665c375b60702345a32c22e55efea9b [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2018 The Chromium Authors
Sam Goto366a1d92019-01-18 21:47:352// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ayu Ishii4aa9d9f2020-05-01 19:49:495#include "content/browser/idle/idle_manager_impl.h"
Sam Goto786548c2019-02-28 01:28:086
Ayu Ishii4aa9d9f2020-05-01 19:49:497#include <utility>
Sam Goto366a1d92019-01-18 21:47:358
Avi Drissmanadac21992023-01-11 23:46:399#include "base/functional/bind.h"
10#include "base/functional/callback_helpers.h"
Ayu Ishii4aa9d9f2020-05-01 19:49:4911#include "content/public/browser/browser_context.h"
Sam Goto366a1d92019-01-18 21:47:3512#include "content/public/browser/permission_controller.h"
Florian Jackya857d582025-04-10 10:13:3313#include "content/public/browser/permission_descriptor_util.h"
Reilly Grantf5f49932021-07-20 03:39:3814#include "content/public/browser/render_frame_host.h"
Andy Paicua6d6d852022-04-28 18:08:3615#include "third_party/blink/public/common/permissions/permission_utils.h"
Sam Goto366a1d92019-01-18 21:47:3516
17namespace content {
18
19namespace {
20
Ayu Ishii4aa9d9f2020-05-01 19:49:4921using blink::mojom::IdleManagerError;
22using blink::mojom::IdleState;
23using blink::mojom::PermissionStatus;
24
Reilly Grant4b6750d2021-11-08 08:42:4625constexpr base::TimeDelta kUserInputThreshold =
26 base::Milliseconds(blink::mojom::IdleManager::kUserInputThresholdMs);
Sam Goto366a1d92019-01-18 21:47:3527
Sam Goto366a1d92019-01-18 21:47:3528} // namespace
29
Reilly Grantf5f49932021-07-20 03:39:3830IdleManagerImpl::IdleManagerImpl(RenderFrameHost* render_frame_host)
Reilly Grant4b6750d2021-11-08 08:42:4631 : render_frame_host_(render_frame_host) {
32 monitors_.set_disconnect_handler(base::BindRepeating(
33 &IdleManagerImpl::OnMonitorDisconnected, base::Unretained(this)));
34}
Sam Goto366a1d92019-01-18 21:47:3535
Ayu Ishii4aa9d9f2020-05-01 19:49:4936IdleManagerImpl::~IdleManagerImpl() {
Sam Goto366a1d92019-01-18 21:47:3537 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Sam Goto366a1d92019-01-18 21:47:3538}
39
Ayu Ishii4aa9d9f2020-05-01 19:49:4940void IdleManagerImpl::CreateService(
Reilly Grant5ac325b2021-07-27 02:55:5641 mojo::PendingReceiver<blink::mojom::IdleManager> receiver) {
Sam Goto366a1d92019-01-18 21:47:3542 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
43
Reilly Grant5ac325b2021-07-27 02:55:5644 receivers_.Add(this, std::move(receiver));
Sam Goto366a1d92019-01-18 21:47:3545}
46
Reilly Grant4b6750d2021-11-08 08:42:4647void IdleManagerImpl::SetIdleOverride(bool is_user_active,
48 bool is_screen_unlocked) {
49 state_override_ = true;
50 observer_.Reset();
51
52 last_state_ = IdleState::New();
53 if (!is_user_active)
54 last_state_->idle_time = base::Seconds(0);
55 last_state_->screen_locked = !is_screen_unlocked;
56
57 for (const auto& monitor : monitors_) {
58 monitor->Update(last_state_->Clone(), /*is_overridden_by_devtools=*/true);
59 }
Maksim Sadyma30263e2020-07-29 17:09:2760}
61
62void IdleManagerImpl::ClearIdleOverride() {
Reilly Grant4b6750d2021-11-08 08:42:4663 state_override_ = false;
64
65 if (monitors_.empty()) {
66 return;
67 }
68
Nicolas Ouellet-Payeur52feb9df2022-05-12 20:28:3769 observer_.Observe(ui::IdlePollingService::GetInstance());
Reilly Grant4b6750d2021-11-08 08:42:4670 last_state_ = CheckIdleState();
71 for (const auto& monitor : monitors_) {
72 monitor->Update(last_state_->Clone(), /*is_overridden_by_devtools=*/false);
73 }
Maksim Sadyma30263e2020-07-29 17:09:2774}
75
Ayu Ishii4aa9d9f2020-05-01 19:49:4976void IdleManagerImpl::AddMonitor(
Gyuyoung Kim5164b1bd2019-08-14 04:17:2777 mojo::PendingRemote<blink::mojom::IdleMonitor> monitor_remote,
78 AddMonitorCallback callback) {
Sam Goto366a1d92019-01-18 21:47:3579 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Sam Goto366a1d92019-01-18 21:47:3580
Reilly Grant5ac325b2021-07-27 02:55:5681 if (!HasPermission()) {
Ayu Ishii4aa9d9f2020-05-01 19:49:4982 std::move(callback).Run(IdleManagerError::kPermissionDisabled, nullptr);
83 return;
84 }
85
Reilly Grant4b6750d2021-11-08 08:42:4686 if (monitors_.empty() && !state_override_) {
Nicolas Ouellet-Payeur52feb9df2022-05-12 20:28:3787 observer_.Observe(ui::IdlePollingService::GetInstance());
Reilly Grant4b6750d2021-11-08 08:42:4688 last_state_ = CheckIdleState();
Reilly Grant980a89b2021-07-24 02:52:5989 }
90
Reilly Grant4b6750d2021-11-08 08:42:4691 monitors_.Add(std::move(monitor_remote));
Sam Goto786548c2019-02-28 01:28:0892
Reilly Grant4b6750d2021-11-08 08:42:4693 std::move(callback).Run(IdleManagerError::kSuccess, last_state_->Clone());
Sam Goto366a1d92019-01-18 21:47:3594}
95
Reilly Grant5ac325b2021-07-27 02:55:5696bool IdleManagerImpl::HasPermission() {
Ayu Ishii4aa9d9f2020-05-01 19:49:4997 PermissionController* permission_controller =
Reilly Grantf5f49932021-07-20 03:39:3898 render_frame_host_->GetBrowserContext()->GetPermissionController();
Ayu Ishii4aa9d9f2020-05-01 19:49:4999 DCHECK(permission_controller);
Illia Klimov4a2cb192022-03-15 06:31:35100 PermissionStatus status =
101 permission_controller->GetPermissionStatusForCurrentDocument(
Florian Jackya857d582025-04-10 10:13:33102 content::PermissionDescriptorUtil::
103 CreatePermissionDescriptorForPermissionType(
104 blink::PermissionType::IDLE_DETECTION),
105 render_frame_host_);
Ayu Ishii4aa9d9f2020-05-01 19:49:49106 return status == PermissionStatus::GRANTED;
107}
108
Reilly Grant4b6750d2021-11-08 08:42:46109void IdleManagerImpl::OnMonitorDisconnected(mojo::RemoteSetElementId id) {
Sam Goto366a1d92019-01-18 21:47:35110 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
111
Sam Goto366a1d92019-01-18 21:47:35112 if (monitors_.empty()) {
Reilly Grant980a89b2021-07-24 02:52:59113 observer_.Reset();
Sam Goto366a1d92019-01-18 21:47:35114 }
115}
116
Reilly Grant980a89b2021-07-24 02:52:59117void IdleManagerImpl::OnIdleStateChange(
Nicolas Ouellet-Payeur52feb9df2022-05-12 20:28:37118 const ui::IdlePollingService::State& state) {
Sam Goto366a1d92019-01-18 21:47:35119 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Sam Goto366a1d92019-01-18 21:47:35120
Daniil Hrybchuk35217192025-02-14 09:34:27121 last_state_ = CreateIdleState(state);
Reilly Grant4b6750d2021-11-08 08:42:46122 for (const auto& monitor : monitors_) {
123 monitor->Update(last_state_->Clone(), /*is_overridden_by_devtools=*/false);
124 }
125}
126
127blink::mojom::IdleStatePtr IdleManagerImpl::CreateIdleState(
Nicolas Ouellet-Payeur52feb9df2022-05-12 20:28:37128 const ui::IdlePollingService::State& state) {
Reilly Grant4b6750d2021-11-08 08:42:46129 auto result = IdleState::New();
130 if (state.idle_time >= kUserInputThreshold) {
131 result->idle_time = state.idle_time - kUserInputThreshold;
132 }
133 result->screen_locked = state.locked;
134 return result;
135}
136
137blink::mojom::IdleStatePtr IdleManagerImpl::CheckIdleState() {
Nicolas Ouellet-Payeur52feb9df2022-05-12 20:28:37138 return CreateIdleState(ui::IdlePollingService::GetInstance()->GetIdleState());
Sam Goto366a1d92019-01-18 21:47:35139}
140
141} // namespace content