blob: 311d1386b6019d926c71b8f4bfeb6c63aa2e9dca [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "extensions/browser/service_worker/worker_id_set.h"
#include <algorithm>
#include <iterator>
#include <memory>
#include "base/logging.h"
#include "content/public/common/child_process_host.h"
#include "extensions/browser/service_worker/worker_id.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
namespace extensions {
namespace {
constexpr int64_t kSmallestVersionId =
blink::mojom::kInvalidServiceWorkerVersionId;
constexpr int kSmallestThreadId = -1;
constexpr int kSmallestRenderProcessId =
content::ChildProcessHost::kInvalidUniqueID;
static_assert(kSmallestVersionId < 0,
"Sentinel version_id must be smaller than any valid version id.");
static_assert(kSmallestThreadId < 0,
"Sentinel thread_id must be smaller than any valid thread id.");
static_assert(
kSmallestRenderProcessId < 0,
"Sentinel render_process_id must be smaller than any valid process id.");
} // namespace
WorkerIdSet::WorkerIdSet() = default;
WorkerIdSet::~WorkerIdSet() = default;
void WorkerIdSet::Add(const WorkerId& worker_id) {
workers_.insert(worker_id);
}
bool WorkerIdSet::Remove(const WorkerId& worker_id) {
return workers_.erase(worker_id) > 0;
}
void WorkerIdSet::RemoveAllForExtension(const ExtensionId& extension_id) {
// Construct a key that is guaranteed to be smaller than any key given a
// |render_process_id|. This facilitates the usage of lower_bound to achieve
// lg(n) runtime.
WorkerId lowest_id{extension_id, kSmallestRenderProcessId, kSmallestVersionId,
kSmallestThreadId};
auto begin_range = workers_.lower_bound(lowest_id);
if (begin_range == workers_.end() ||
begin_range->extension_id != extension_id) {
return; // No entries.
}
auto end_range = std::next(begin_range);
while (end_range != workers_.end() && end_range->extension_id == extension_id)
++end_range;
workers_.erase(begin_range, end_range);
}
bool WorkerIdSet::Contains(const WorkerId& worker_id) const {
return workers_.count(worker_id) != 0;
}
std::vector<WorkerId> WorkerIdSet::GetAllForExtension(
const ExtensionId& extension_id,
int render_process_id) const {
// See RemoveAllForExtension() notes for |id| construction.
WorkerId id{extension_id, render_process_id, kSmallestVersionId,
kSmallestThreadId};
auto begin_range = workers_.lower_bound(id);
if (begin_range == workers_.end() ||
begin_range->extension_id > extension_id ||
begin_range->render_process_id > render_process_id) {
return std::vector<WorkerId>(); // No entries.
}
auto end_range = std::next(begin_range);
while (end_range != workers_.end() &&
end_range->extension_id == extension_id &&
// If |extension_id| matches, then |end_range->render_process_id| must
// be GTE to |render_process_id|.
end_range->render_process_id == render_process_id) {
++end_range;
}
return std::vector<WorkerId>(begin_range, end_range);
}
std::vector<WorkerId> WorkerIdSet::GetAllForTesting() const {
return std::vector<WorkerId>(workers_.begin(), workers_.end());
}
} // namespace extensions