• 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 #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