blob: e6f0354fe665c375b60702345a32c22e55efea9b [file] [log] [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/idle/idle_manager_impl.h"
#include <utility>
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/permission_controller.h"
#include "content/public/browser/permission_descriptor_util.h"
#include "content/public/browser/render_frame_host.h"
#include "third_party/blink/public/common/permissions/permission_utils.h"
namespace content {
namespace {
using blink::mojom::IdleManagerError;
using blink::mojom::IdleState;
using blink::mojom::PermissionStatus;
constexpr base::TimeDelta kUserInputThreshold =
base::Milliseconds(blink::mojom::IdleManager::kUserInputThresholdMs);
} // namespace
IdleManagerImpl::IdleManagerImpl(RenderFrameHost* render_frame_host)
: render_frame_host_(render_frame_host) {
monitors_.set_disconnect_handler(base::BindRepeating(
&IdleManagerImpl::OnMonitorDisconnected, base::Unretained(this)));
}
IdleManagerImpl::~IdleManagerImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
void IdleManagerImpl::CreateService(
mojo::PendingReceiver<blink::mojom::IdleManager> receiver) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
receivers_.Add(this, std::move(receiver));
}
void IdleManagerImpl::SetIdleOverride(bool is_user_active,
bool is_screen_unlocked) {
state_override_ = true;
observer_.Reset();
last_state_ = IdleState::New();
if (!is_user_active)
last_state_->idle_time = base::Seconds(0);
last_state_->screen_locked = !is_screen_unlocked;
for (const auto& monitor : monitors_) {
monitor->Update(last_state_->Clone(), /*is_overridden_by_devtools=*/true);
}
}
void IdleManagerImpl::ClearIdleOverride() {
state_override_ = false;
if (monitors_.empty()) {
return;
}
observer_.Observe(ui::IdlePollingService::GetInstance());
last_state_ = CheckIdleState();
for (const auto& monitor : monitors_) {
monitor->Update(last_state_->Clone(), /*is_overridden_by_devtools=*/false);
}
}
void IdleManagerImpl::AddMonitor(
mojo::PendingRemote<blink::mojom::IdleMonitor> monitor_remote,
AddMonitorCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!HasPermission()) {
std::move(callback).Run(IdleManagerError::kPermissionDisabled, nullptr);
return;
}
if (monitors_.empty() && !state_override_) {
observer_.Observe(ui::IdlePollingService::GetInstance());
last_state_ = CheckIdleState();
}
monitors_.Add(std::move(monitor_remote));
std::move(callback).Run(IdleManagerError::kSuccess, last_state_->Clone());
}
bool IdleManagerImpl::HasPermission() {
PermissionController* permission_controller =
render_frame_host_->GetBrowserContext()->GetPermissionController();
DCHECK(permission_controller);
PermissionStatus status =
permission_controller->GetPermissionStatusForCurrentDocument(
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
blink::PermissionType::IDLE_DETECTION),
render_frame_host_);
return status == PermissionStatus::GRANTED;
}
void IdleManagerImpl::OnMonitorDisconnected(mojo::RemoteSetElementId id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (monitors_.empty()) {
observer_.Reset();
}
}
void IdleManagerImpl::OnIdleStateChange(
const ui::IdlePollingService::State& state) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
last_state_ = CreateIdleState(state);
for (const auto& monitor : monitors_) {
monitor->Update(last_state_->Clone(), /*is_overridden_by_devtools=*/false);
}
}
blink::mojom::IdleStatePtr IdleManagerImpl::CreateIdleState(
const ui::IdlePollingService::State& state) {
auto result = IdleState::New();
if (state.idle_time >= kUserInputThreshold) {
result->idle_time = state.idle_time - kUserInputThreshold;
}
result->screen_locked = state.locked;
return result;
}
blink::mojom::IdleStatePtr IdleManagerImpl::CheckIdleState() {
return CreateIdleState(ui::IdlePollingService::GetInstance()->GetIdleState());
}
} // namespace content