| // 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" |
| #include "include/base/cef_macros.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: |
| 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<IdType, ObjectType> InfoMap; |
| // Map browser ID to InfoMap instance. |
| typedef std::map<int, InfoMap*> BrowserInfoMap; |
| |
| BrowserInfoMap browser_info_map_; |
| |
| DISALLOW_COPY_AND_ASSIGN(CefBrowserInfoMap); |
| }; |
| |
| #endif // CEF_LIBCEF_DLL_WRAPPER_CEF_BROWSER_INFO_MAP_H_ |