blob: 89f2fbd8aaf9648f1a2c03d0dfe3513333fff0f7 [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/permissions/permission_request_queue.h"
#include <algorithm>
#include "components/permissions/permission_request.h"
#include "components/permissions/permission_util.h"
namespace permissions {
PermissionRequestQueue::PermissionRequestQueue()
: queued_requests_(static_cast<size_t>(Priority::kNum)) {}
PermissionRequestQueue::~PermissionRequestQueue() = default;
bool PermissionRequestQueue::IsEmpty() const {
return !size_;
}
bool PermissionRequestQueue::Contains(PermissionRequest* request) const {
for (const auto& request_list : queued_requests_) {
if (std::ranges::any_of(request_list,
[=](const auto& request_list_element) {
return request_list_element.get() == request;
})) {
return true;
}
}
return false;
}
void PermissionRequestQueue::Push(
std::unique_ptr<permissions::PermissionRequest> request) {
Priority priority = DetermineRequestPriority(request.get());
// High priority requests are always pushed to the back since they don't use
// the chip.
if (priority == Priority::kHigh) {
PushBackInternal(std::move(request), priority);
return;
}
// If the platform does not support the chip, push to the back.
if (!PermissionUtil::DoesPlatformSupportChip()) {
PushBackInternal(std::move(request), priority);
return;
}
// Otherwise push to the front since chip requests use FILO ordering.
PushFrontInternal(std::move(request), priority);
}
void PermissionRequestQueue::PushFront(
std::unique_ptr<permissions::PermissionRequest> request) {
Priority priority = DetermineRequestPriority(request.get());
PushFrontInternal(std::move(request), priority);
}
void PermissionRequestQueue::PushBack(
std::unique_ptr<permissions::PermissionRequest> request) {
Priority priority = DetermineRequestPriority(request.get());
PushBackInternal(std::move(request), priority);
}
std::unique_ptr<permissions::PermissionRequest> PermissionRequestQueue::Pop() {
std::vector<base::circular_deque<
std::unique_ptr<permissions::PermissionRequest>>>::reverse_iterator it;
CHECK(!IsEmpty());
// Skip entries that contain empty queues.
for (it = queued_requests_.rbegin();
it != queued_requests_.rend() && it->empty(); ++it) {
}
CHECK(it != queued_requests_.rend());
std::unique_ptr<permissions::PermissionRequest> front =
std::move(it->front());
it->pop_front();
--size_;
return front;
}
PermissionRequest* PermissionRequestQueue::Peek() const {
CHECK(!IsEmpty());
std::vector<base::circular_deque<
std::unique_ptr<permissions::PermissionRequest>>>::const_reverse_iterator
it;
// Skip entries that contain empty queues.
for (it = queued_requests_.rbegin();
it != queued_requests_.rend() && it->empty(); ++it) {
}
CHECK(it != queued_requests_.rend());
return it->front().get();
}
PermissionRequest* PermissionRequestQueue::FindDuplicate(
PermissionRequest* request) const {
auto priority = DetermineRequestPriority(request);
const auto& queued_request_list =
queued_requests_[static_cast<size_t>(priority)];
for (const auto& queued_request : queued_request_list) {
if (request->IsDuplicateOf(queued_request.get())) {
return queued_request.get();
}
}
return nullptr;
}
PermissionRequestQueue::const_iterator PermissionRequestQueue::begin() const {
return queued_requests_.begin();
}
PermissionRequestQueue::const_iterator PermissionRequestQueue::end() const {
return queued_requests_.end();
}
// static
PermissionRequestQueue::Priority
PermissionRequestQueue::DetermineRequestPriority(
permissions::PermissionRequest* request) {
if (request->IsEmbeddedPermissionElementInitiated()) {
return Priority::kHigh;
}
if (permissions::PermissionUtil::DoesPlatformSupportChip() &&
permissions::PermissionUtil::IsLowPriorityPermissionRequest(request)) {
return Priority::kLow;
}
return Priority::kMedium;
}
void PermissionRequestQueue::PushFrontInternal(
std::unique_ptr<permissions::PermissionRequest> request,
Priority priority) {
queued_requests_[static_cast<size_t>(priority)].push_front(
std::move(request));
++size_;
}
void PermissionRequestQueue::PushBackInternal(
std::unique_ptr<permissions::PermissionRequest> request,
Priority priority) {
queued_requests_[static_cast<size_t>(priority)].push_back(std::move(request));
++size_;
}
} // namespace permissions