910e62b5创建于 1月15日历史提交
// 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