1 // Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights 2 // reserved. Use of this source code is governed by a BSD-style license that 3 // can be found in the LICENSE file. 4 5 #ifndef CEF_LIBCEF_DLL_WRAPPER_CEF_BROWSER_INFO_MAP_H_ 6 #define CEF_LIBCEF_DLL_WRAPPER_CEF_BROWSER_INFO_MAP_H_ 7 #pragma once 8 9 #include <map> 10 11 #include "include/base/cef_logging.h" 12 13 // Default traits for CefBrowserInfoMap. Override to provide different object 14 // destruction behavior. 15 template <typename ObjectType> 16 struct DefaultCefBrowserInfoMapTraits { DestructDefaultCefBrowserInfoMapTraits17 static void Destruct(ObjectType info) { delete info; } 18 }; 19 20 // Maps an arbitrary IdType to an arbitrary ObjectType on a per-browser basis. 21 template <typename IdType, 22 typename ObjectType, 23 typename Traits = DefaultCefBrowserInfoMapTraits<ObjectType>> 24 class CefBrowserInfoMap { 25 public: 26 // Implement this interface to visit and optionally delete objects in the map. 27 class Visitor { 28 public: 29 using InfoIdType = IdType; 30 using InfoObjectType = ObjectType; 31 32 // Called once for each info object. Set |remove| to true to remove the 33 // object from the map. It is safe to destruct removed objects in this 34 // callback. Return true to continue iterating or false to stop iterating. 35 virtual bool OnNextInfo(int browser_id, 36 InfoIdType info_id, 37 InfoObjectType info, 38 bool* remove) = 0; 39 40 protected: ~Visitor()41 virtual ~Visitor() {} 42 }; 43 44 CefBrowserInfoMap() = default; 45 46 CefBrowserInfoMap(const CefBrowserInfoMap&) = delete; 47 CefBrowserInfoMap& operator=(const CefBrowserInfoMap&) = delete; 48 ~CefBrowserInfoMap()49 ~CefBrowserInfoMap() { clear(); } 50 51 // Add an object associated with the specified ID values. Add(int browser_id,IdType info_id,ObjectType info)52 void Add(int browser_id, IdType info_id, ObjectType info) { 53 InfoMap* info_map = nullptr; 54 typename BrowserInfoMap::const_iterator it_browser = 55 browser_info_map_.find(browser_id); 56 if (it_browser == browser_info_map_.end()) { 57 // No InfoMap exists for the browser ID so create it. 58 info_map = new InfoMap; 59 browser_info_map_.insert(std::make_pair(browser_id, info_map)); 60 } else { 61 info_map = it_browser->second; 62 // The specified ID should not already exist in the map. 63 DCHECK(info_map->find(info_id) == info_map->end()); 64 } 65 66 info_map->insert(std::make_pair(info_id, info)); 67 } 68 69 // Find the object with the specified ID values. |visitor| can optionally be 70 // used to evaluate or remove the object at the same time. If the object is 71 // removed using the Visitor the caller is responsible for destroying it. Find(int browser_id,IdType info_id,Visitor * vistor)72 ObjectType Find(int browser_id, IdType info_id, Visitor* vistor) { 73 if (browser_info_map_.empty()) 74 return ObjectType(); 75 76 typename BrowserInfoMap::iterator it_browser = 77 browser_info_map_.find(browser_id); 78 if (it_browser == browser_info_map_.end()) 79 return ObjectType(); 80 81 InfoMap* info_map = it_browser->second; 82 typename InfoMap::iterator it_info = info_map->find(info_id); 83 if (it_info == info_map->end()) 84 return ObjectType(); 85 86 ObjectType info = it_info->second; 87 88 bool remove = false; 89 if (vistor) 90 vistor->OnNextInfo(browser_id, it_info->first, info, &remove); 91 if (remove) { 92 info_map->erase(it_info); 93 94 if (info_map->empty()) { 95 // No more entries in the InfoMap so remove it. 96 browser_info_map_.erase(it_browser); 97 delete info_map; 98 } 99 } 100 101 return info; 102 } 103 104 // Find all objects. If any objects are removed using the Visitor the caller 105 // is responsible for destroying them. FindAll(Visitor * visitor)106 void FindAll(Visitor* visitor) { 107 DCHECK(visitor); 108 109 if (browser_info_map_.empty()) 110 return; 111 112 bool remove, keepgoing = true; 113 114 typename BrowserInfoMap::iterator it_browser = browser_info_map_.begin(); 115 while (it_browser != browser_info_map_.end()) { 116 InfoMap* info_map = it_browser->second; 117 118 typename InfoMap::iterator it_info = info_map->begin(); 119 while (it_info != info_map->end()) { 120 remove = false; 121 keepgoing = visitor->OnNextInfo(it_browser->first, it_info->first, 122 it_info->second, &remove); 123 124 if (remove) 125 info_map->erase(it_info++); 126 else 127 ++it_info; 128 129 if (!keepgoing) 130 break; 131 } 132 133 if (info_map->empty()) { 134 // No more entries in the InfoMap so remove it. 135 browser_info_map_.erase(it_browser++); 136 delete info_map; 137 } else { 138 ++it_browser; 139 } 140 141 if (!keepgoing) 142 break; 143 } 144 } 145 146 // Find all objects associated with the specified browser. If any objects are 147 // removed using the Visitor the caller is responsible for destroying them. FindAll(int browser_id,Visitor * visitor)148 void FindAll(int browser_id, Visitor* visitor) { 149 DCHECK(visitor); 150 151 if (browser_info_map_.empty()) 152 return; 153 154 typename BrowserInfoMap::iterator it_browser = 155 browser_info_map_.find(browser_id); 156 if (it_browser == browser_info_map_.end()) 157 return; 158 159 InfoMap* info_map = it_browser->second; 160 bool remove, keepgoing; 161 162 typename InfoMap::iterator it_info = info_map->begin(); 163 while (it_info != info_map->end()) { 164 remove = false; 165 keepgoing = visitor->OnNextInfo(browser_id, it_info->first, 166 it_info->second, &remove); 167 168 if (remove) 169 info_map->erase(it_info++); 170 else 171 ++it_info; 172 173 if (!keepgoing) 174 break; 175 } 176 177 if (info_map->empty()) { 178 // No more entries in the InfoMap so remove it. 179 browser_info_map_.erase(it_browser); 180 delete info_map; 181 } 182 } 183 184 // Returns true if the map is empty. empty()185 bool empty() const { return browser_info_map_.empty(); } 186 187 // Returns the number of objects in the map. size()188 size_t size() const { 189 if (browser_info_map_.empty()) 190 return 0; 191 192 size_t size = 0; 193 typename BrowserInfoMap::const_iterator it_browser = 194 browser_info_map_.begin(); 195 for (; it_browser != browser_info_map_.end(); ++it_browser) 196 size += it_browser->second->size(); 197 return size; 198 } 199 200 // Returns the number of objects in the map that are associated with the 201 // specified browser. size(int browser_id)202 size_t size(int browser_id) const { 203 if (browser_info_map_.empty()) 204 return 0; 205 206 typename BrowserInfoMap::const_iterator it_browser = 207 browser_info_map_.find(browser_id); 208 if (it_browser != browser_info_map_.end()) 209 return it_browser->second->size(); 210 211 return 0; 212 } 213 214 // Remove all objects from the map. The objects will be destructed. clear()215 void clear() { 216 if (browser_info_map_.empty()) 217 return; 218 219 typename BrowserInfoMap::const_iterator it_browser = 220 browser_info_map_.begin(); 221 for (; it_browser != browser_info_map_.end(); ++it_browser) { 222 InfoMap* info_map = it_browser->second; 223 typename InfoMap::const_iterator it_info = info_map->begin(); 224 for (; it_info != info_map->end(); ++it_info) 225 Traits::Destruct(it_info->second); 226 delete info_map; 227 } 228 browser_info_map_.clear(); 229 } 230 231 // Remove all objects from the map that are associated with the specified 232 // browser. The objects will be destructed. clear(int browser_id)233 void clear(int browser_id) { 234 if (browser_info_map_.empty()) 235 return; 236 237 typename BrowserInfoMap::iterator it_browser = 238 browser_info_map_.find(browser_id); 239 if (it_browser == browser_info_map_.end()) 240 return; 241 242 InfoMap* info_map = it_browser->second; 243 typename InfoMap::const_iterator it_info = info_map->begin(); 244 for (; it_info != info_map->end(); ++it_info) 245 Traits::Destruct(it_info->second); 246 247 browser_info_map_.erase(it_browser); 248 delete info_map; 249 } 250 251 private: 252 // Map IdType to ObjectType instance. 253 using InfoMap = std::map<IdType, ObjectType>; 254 // Map browser ID to InfoMap instance. 255 using BrowserInfoMap = std::map<int, InfoMap*>; 256 257 BrowserInfoMap browser_info_map_; 258 }; 259 260 #endif // CEF_LIBCEF_DLL_WRAPPER_CEF_BROWSER_INFO_MAP_H_ 261