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