cef/libcef_dll/wrapper/cef_browser_info_map.h
2023-01-04 17:47:17 -05:00

282 lines
8.0 KiB
C++

// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#ifndef CEF_LIBCEF_DLL_WRAPPER_CEF_BROWSER_INFO_MAP_H_
#define CEF_LIBCEF_DLL_WRAPPER_CEF_BROWSER_INFO_MAP_H_
#pragma once
#include <map>
#include "include/base/cef_logging.h"
// Default traits for CefBrowserInfoMap. Override to provide different object
// destruction behavior.
template <typename ObjectType>
struct DefaultCefBrowserInfoMapTraits {
static void Destruct(ObjectType info) { delete info; }
};
// Maps an arbitrary IdType to an arbitrary ObjectType on a per-browser basis.
template <typename IdType,
typename ObjectType,
typename Traits = DefaultCefBrowserInfoMapTraits<ObjectType>>
class CefBrowserInfoMap {
public:
// Implement this interface to visit and optionally delete objects in the map.
class Visitor {
public:
using InfoIdType = IdType;
using InfoObjectType = ObjectType;
// Called once for each info object. Set |remove| to true to remove the
// object from the map. It is safe to destruct removed objects in this
// callback. Return true to continue iterating or false to stop iterating.
virtual bool OnNextInfo(int browser_id,
InfoIdType info_id,
InfoObjectType info,
bool* remove) = 0;
protected:
virtual ~Visitor() {}
};
CefBrowserInfoMap() = default;
CefBrowserInfoMap(const CefBrowserInfoMap&) = delete;
CefBrowserInfoMap& operator=(const CefBrowserInfoMap&) = delete;
~CefBrowserInfoMap() { clear(); }
// Add an object associated with the specified ID values.
void Add(int browser_id, IdType info_id, ObjectType info) {
InfoMap* info_map = nullptr;
typename BrowserInfoMap::const_iterator it_browser =
browser_info_map_.find(browser_id);
if (it_browser == browser_info_map_.end()) {
// No InfoMap exists for the browser ID so create it.
info_map = new InfoMap;
browser_info_map_.insert(std::make_pair(browser_id, info_map));
} else {
info_map = it_browser->second;
// The specified ID should not already exist in the map.
DCHECK(info_map->find(info_id) == info_map->end());
}
info_map->insert(std::make_pair(info_id, info));
}
// Find the object with the specified ID values. |visitor| can optionally be
// used to evaluate or remove the object at the same time. If the object is
// removed using the Visitor the caller is responsible for destroying it.
ObjectType Find(int browser_id, IdType info_id, Visitor* vistor) {
if (browser_info_map_.empty()) {
return ObjectType();
}
typename BrowserInfoMap::iterator it_browser =
browser_info_map_.find(browser_id);
if (it_browser == browser_info_map_.end()) {
return ObjectType();
}
InfoMap* info_map = it_browser->second;
typename InfoMap::iterator it_info = info_map->find(info_id);
if (it_info == info_map->end()) {
return ObjectType();
}
ObjectType info = it_info->second;
bool remove = false;
if (vistor) {
vistor->OnNextInfo(browser_id, it_info->first, info, &remove);
}
if (remove) {
info_map->erase(it_info);
if (info_map->empty()) {
// No more entries in the InfoMap so remove it.
browser_info_map_.erase(it_browser);
delete info_map;
}
}
return info;
}
// Find all objects. If any objects are removed using the Visitor the caller
// is responsible for destroying them.
void FindAll(Visitor* visitor) {
DCHECK(visitor);
if (browser_info_map_.empty()) {
return;
}
bool remove, keepgoing = true;
typename BrowserInfoMap::iterator it_browser = browser_info_map_.begin();
while (it_browser != browser_info_map_.end()) {
InfoMap* info_map = it_browser->second;
typename InfoMap::iterator it_info = info_map->begin();
while (it_info != info_map->end()) {
remove = false;
keepgoing = visitor->OnNextInfo(it_browser->first, it_info->first,
it_info->second, &remove);
if (remove) {
info_map->erase(it_info++);
} else {
++it_info;
}
if (!keepgoing) {
break;
}
}
if (info_map->empty()) {
// No more entries in the InfoMap so remove it.
browser_info_map_.erase(it_browser++);
delete info_map;
} else {
++it_browser;
}
if (!keepgoing) {
break;
}
}
}
// Find all objects associated with the specified browser. If any objects are
// removed using the Visitor the caller is responsible for destroying them.
void FindAll(int browser_id, Visitor* visitor) {
DCHECK(visitor);
if (browser_info_map_.empty()) {
return;
}
typename BrowserInfoMap::iterator it_browser =
browser_info_map_.find(browser_id);
if (it_browser == browser_info_map_.end()) {
return;
}
InfoMap* info_map = it_browser->second;
bool remove, keepgoing;
typename InfoMap::iterator it_info = info_map->begin();
while (it_info != info_map->end()) {
remove = false;
keepgoing = visitor->OnNextInfo(browser_id, it_info->first,
it_info->second, &remove);
if (remove) {
info_map->erase(it_info++);
} else {
++it_info;
}
if (!keepgoing) {
break;
}
}
if (info_map->empty()) {
// No more entries in the InfoMap so remove it.
browser_info_map_.erase(it_browser);
delete info_map;
}
}
// Returns true if the map is empty.
bool empty() const { return browser_info_map_.empty(); }
// Returns the number of objects in the map.
size_t size() const {
if (browser_info_map_.empty()) {
return 0;
}
size_t size = 0;
typename BrowserInfoMap::const_iterator it_browser =
browser_info_map_.begin();
for (; it_browser != browser_info_map_.end(); ++it_browser) {
size += it_browser->second->size();
}
return size;
}
// Returns the number of objects in the map that are associated with the
// specified browser.
size_t size(int browser_id) const {
if (browser_info_map_.empty()) {
return 0;
}
typename BrowserInfoMap::const_iterator it_browser =
browser_info_map_.find(browser_id);
if (it_browser != browser_info_map_.end()) {
return it_browser->second->size();
}
return 0;
}
// Remove all objects from the map. The objects will be destructed.
void clear() {
if (browser_info_map_.empty()) {
return;
}
typename BrowserInfoMap::const_iterator it_browser =
browser_info_map_.begin();
for (; it_browser != browser_info_map_.end(); ++it_browser) {
InfoMap* info_map = it_browser->second;
typename InfoMap::const_iterator it_info = info_map->begin();
for (; it_info != info_map->end(); ++it_info) {
Traits::Destruct(it_info->second);
}
delete info_map;
}
browser_info_map_.clear();
}
// Remove all objects from the map that are associated with the specified
// browser. The objects will be destructed.
void clear(int browser_id) {
if (browser_info_map_.empty()) {
return;
}
typename BrowserInfoMap::iterator it_browser =
browser_info_map_.find(browser_id);
if (it_browser == browser_info_map_.end()) {
return;
}
InfoMap* info_map = it_browser->second;
typename InfoMap::const_iterator it_info = info_map->begin();
for (; it_info != info_map->end(); ++it_info) {
Traits::Destruct(it_info->second);
}
browser_info_map_.erase(it_browser);
delete info_map;
}
private:
// Map IdType to ObjectType instance.
using InfoMap = std::map<IdType, ObjectType>;
// Map browser ID to InfoMap instance.
using BrowserInfoMap = std::map<int, InfoMap*>;
BrowserInfoMap browser_info_map_;
};
#endif // CEF_LIBCEF_DLL_WRAPPER_CEF_BROWSER_INFO_MAP_H_