// 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 #include "include/base/cef_logging.h" #include "include/base/cef_macros.h" // Default traits for CefBrowserInfoMap. Override to provide different object // destruction behavior. template struct DefaultCefBrowserInfoMapTraits { static void Destruct(ObjectType info) { delete info; } }; // Maps an arbitrary IdType to an arbitrary ObjectType on a per-browser basis. template > class CefBrowserInfoMap { public: // Implement this interface to visit and optionally delete objects in the map. class Visitor { public: typedef IdType InfoIdType; typedef ObjectType InfoObjectType; // 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() {} ~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. typedef std::map InfoMap; // Map browser ID to InfoMap instance. typedef std::map BrowserInfoMap; BrowserInfoMap browser_info_map_; DISALLOW_COPY_AND_ASSIGN(CefBrowserInfoMap); }; #endif // CEF_LIBCEF_DLL_WRAPPER_CEF_BROWSER_INFO_MAP_H_