• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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