OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef EXTENSIONS_BROWSER_API_API_RESOURCE_MANAGER_H_ | 5 #ifndef EXTENSIONS_BROWSER_API_API_RESOURCE_MANAGER_H_ |
6 #define EXTENSIONS_BROWSER_API_API_RESOURCE_MANAGER_H_ | 6 #define EXTENSIONS_BROWSER_API_API_RESOURCE_MANAGER_H_ |
7 | 7 |
8 #include <map> | 8 #include <map> |
9 | 9 |
10 #include "base/containers/hash_tables.h" | 10 #include "base/containers/hash_tables.h" |
(...skipping 18 matching lines...) Expand all Loading... | |
29 class BluetoothSocketEventDispatcher; | 29 class BluetoothSocketEventDispatcher; |
30 } | 30 } |
31 | 31 |
32 namespace core_api { | 32 namespace core_api { |
33 class SerialEventDispatcher; | 33 class SerialEventDispatcher; |
34 class TCPServerSocketEventDispatcher; | 34 class TCPServerSocketEventDispatcher; |
35 class TCPSocketEventDispatcher; | 35 class TCPSocketEventDispatcher; |
36 class UDPSocketEventDispatcher; | 36 class UDPSocketEventDispatcher; |
37 } | 37 } |
38 | 38 |
39 template <typename T> | |
40 struct NamedThreadTraits { | |
41 static bool IsCalledOnValidThread() { | |
42 return content::BrowserThread::CurrentlyOn(T::kThreadId); | |
43 } | |
44 | |
45 static bool IsMessageLoopValid() { | |
46 return content::BrowserThread::IsMessageLoopValid(T::kThreadId); | |
47 } | |
48 | |
49 static scoped_refptr<base::SequencedTaskRunner> GetSequencedTaskRunner() { | |
50 return content::BrowserThread::GetMessageLoopProxyForThread(T::kThreadId); | |
51 } | |
52 }; | |
53 | |
54 template <typename T> | |
55 struct TestThreadTraits { | |
56 static bool IsCalledOnValidThread() { | |
57 return content::BrowserThread::CurrentlyOn(thread_id_); | |
58 } | |
59 | |
60 static bool IsMessageLoopValid() { | |
61 return content::BrowserThread::IsMessageLoopValid(thread_id_); | |
62 } | |
63 | |
64 static scoped_refptr<base::SequencedTaskRunner> GetSequencedTaskRunner() { | |
65 return content::BrowserThread::GetMessageLoopProxyForThread(thread_id_); | |
66 } | |
67 | |
68 static content::BrowserThread::ID thread_id_; | |
69 }; | |
70 | |
71 template <typename T> | |
72 content::BrowserThread::ID TestThreadTraits<T>::thread_id_ = | |
73 content::BrowserThread::IO; | |
74 | |
39 // An ApiResourceManager manages the lifetime of a set of resources that | 75 // An ApiResourceManager manages the lifetime of a set of resources that |
40 // ApiFunctions use. Examples are sockets or USB connections. | 76 // that live on named threads (i.e. BrowserThread::IO) which ApiFunctions use. |
77 // Examples of such resources are sockets or USB connections. | |
41 // | 78 // |
42 // Users of this class should define kThreadId to be the thread that | 79 // Users of this class should define kThreadId to be the thread that |
43 // ApiResourceManager to works on. The default is defined in ApiResource. | 80 // ApiResourceManager to works on. The default is defined in ApiResource. |
44 // The user must also define a static const char* service_name() that returns | 81 // The user must also define a static const char* service_name() that returns |
45 // the name of the service, and in order for ApiResourceManager to use | 82 // the name of the service, and in order for ApiResourceManager to use |
46 // service_name() friend this class. | 83 // service_name() friend this class. |
47 // | 84 // |
48 // In the cc file the user must define a GetFactoryInstance() and manage their | 85 // In the cc file the user must define a GetFactoryInstance() and manage their |
49 // own instances (typically using LazyInstance or Singleton). | 86 // own instances (typically using LazyInstance or Singleton). |
50 // | 87 // |
(...skipping 14 matching lines...) Expand all Loading... | |
65 // static base::LazyInstance<BrowserContextKeyedAPIFactory< | 102 // static base::LazyInstance<BrowserContextKeyedAPIFactory< |
66 // ApiResourceManager<Resource> > > | 103 // ApiResourceManager<Resource> > > |
67 // g_factory = LAZY_INSTANCE_INITIALIZER; | 104 // g_factory = LAZY_INSTANCE_INITIALIZER; |
68 // | 105 // |
69 // | 106 // |
70 // template <> | 107 // template <> |
71 // BrowserContextKeyedAPIFactory<ApiResourceManager<Resource> >* | 108 // BrowserContextKeyedAPIFactory<ApiResourceManager<Resource> >* |
72 // ApiResourceManager<Resource>::GetFactoryInstance() { | 109 // ApiResourceManager<Resource>::GetFactoryInstance() { |
73 // return g_factory.Pointer(); | 110 // return g_factory.Pointer(); |
74 // } | 111 // } |
75 template <class T> | 112 template <class T, typename ThreadingTraits = NamedThreadTraits<T> > |
76 class ApiResourceManager : public BrowserContextKeyedAPI, | 113 class ApiResourceManager : public BrowserContextKeyedAPI, |
77 public base::NonThreadSafe, | 114 public base::NonThreadSafe, |
78 public content::NotificationObserver { | 115 public content::NotificationObserver { |
79 public: | 116 public: |
80 explicit ApiResourceManager(content::BrowserContext* context) | 117 explicit ApiResourceManager(content::BrowserContext* context) |
81 : thread_id_(T::kThreadId), data_(new ApiResourceData(thread_id_)) { | 118 : data_(new ApiResourceData()) { |
82 registrar_.Add(this, | 119 registrar_.Add(this, |
83 chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED, | 120 chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED, |
84 content::NotificationService::AllSources()); | 121 content::NotificationService::AllSources()); |
85 registrar_.Add(this, | 122 registrar_.Add(this, |
86 chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED, | 123 chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED, |
87 content::NotificationService::AllSources()); | 124 content::NotificationService::AllSources()); |
88 } | 125 } |
89 | |
90 // For Testing. | 126 // For Testing. |
91 static ApiResourceManager<T>* CreateApiResourceManagerForTest( | 127 static ApiResourceManager<T, TestThreadTraits<T> >* |
92 content::BrowserContext* context, | 128 CreateApiResourceManagerForTest(content::BrowserContext* context, |
93 content::BrowserThread::ID thread_id) { | 129 content::BrowserThread::ID thread_id) { |
94 ApiResourceManager* manager = new ApiResourceManager<T>(context); | 130 TestThreadTraits<T>::thread_id_ = thread_id; |
95 manager->thread_id_ = thread_id; | 131 ApiResourceManager<T, TestThreadTraits<T> >* manager = |
96 manager->data_ = new ApiResourceData(thread_id); | 132 new ApiResourceManager<T, TestThreadTraits<T> >(context); |
97 return manager; | 133 return manager; |
98 } | 134 } |
99 | 135 |
100 virtual ~ApiResourceManager() { | 136 virtual ~ApiResourceManager() { |
101 DCHECK(CalledOnValidThread()); | 137 DCHECK(CalledOnValidThread()); |
102 DCHECK(content::BrowserThread::IsMessageLoopValid(thread_id_)) | 138 DCHECK(ThreadingTraits::IsMessageLoopValid()) |
103 << "A unit test is using an ApiResourceManager but didn't provide " | 139 << "A unit test is using an ApiResourceManager but didn't provide " |
104 "the thread message loop needed for that kind of resource. " | 140 "the thread message loop needed for that kind of resource. " |
105 "Please ensure that the appropriate message loop is operational."; | 141 "Please ensure that the appropriate message loop is operational."; |
106 | 142 |
107 data_->InititateCleanup(); | 143 data_->InititateCleanup(); |
108 } | 144 } |
109 | 145 |
110 // BrowserContextKeyedAPI implementation. | |
111 static BrowserContextKeyedAPIFactory<ApiResourceManager<T> >* | |
112 GetFactoryInstance(); | |
113 | |
114 // Convenience method to get the ApiResourceManager for a profile. | |
115 static ApiResourceManager<T>* Get(content::BrowserContext* context) { | |
116 return BrowserContextKeyedAPIFactory<ApiResourceManager<T> >::Get(context); | |
117 } | |
118 | |
119 // Takes ownership. | 146 // Takes ownership. |
120 int Add(T* api_resource) { return data_->Add(api_resource); } | 147 int Add(T* api_resource) { return data_->Add(api_resource); } |
121 | 148 |
122 void Remove(const std::string& extension_id, int api_resource_id) { | 149 void Remove(const std::string& extension_id, int api_resource_id) { |
123 data_->Remove(extension_id, api_resource_id); | 150 data_->Remove(extension_id, api_resource_id); |
124 } | 151 } |
125 | 152 |
126 T* Get(const std::string& extension_id, int api_resource_id) { | 153 T* Get(const std::string& extension_id, int api_resource_id) { |
127 return data_->Get(extension_id, api_resource_id); | 154 return data_->Get(extension_id, api_resource_id); |
128 } | 155 } |
129 | 156 |
130 base::hash_set<int>* GetResourceIds(const std::string& extension_id) { | 157 base::hash_set<int>* GetResourceIds(const std::string& extension_id) { |
131 return data_->GetResourceIds(extension_id); | 158 return data_->GetResourceIds(extension_id); |
132 } | 159 } |
133 | 160 |
161 // BrowserContextKeyedAPI implementation. | |
162 static BrowserContextKeyedAPIFactory<ApiResourceManager<T> >* | |
163 GetFactoryInstance(); | |
164 | |
165 // Convenience method to get the ApiResourceManager for a profile. | |
166 static ApiResourceManager<T>* Get(content::BrowserContext* context) { | |
167 return BrowserContextKeyedAPIFactory<ApiResourceManager<T> >::Get(context); | |
168 } | |
169 | |
170 // BrowserContextKeyedAPI implementation. | |
171 static const char* service_name() { return T::service_name(); } | |
172 | |
134 protected: | 173 protected: |
135 // content::NotificationObserver: | 174 // content::NotificationObserver: |
136 virtual void Observe(int type, | 175 virtual void Observe(int type, |
137 const content::NotificationSource& source, | 176 const content::NotificationSource& source, |
138 const content::NotificationDetails& details) OVERRIDE { | 177 const content::NotificationDetails& details) OVERRIDE { |
139 switch (type) { | 178 switch (type) { |
140 case chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED: { | 179 case chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED: { |
141 std::string id = content::Details<extensions::UnloadedExtensionInfo>( | 180 std::string id = content::Details<extensions::UnloadedExtensionInfo>( |
142 details)->extension->id(); | 181 details)->extension->id(); |
143 data_->InitiateExtensionUnloadedCleanup(id); | 182 data_->InitiateExtensionUnloadedCleanup(id); |
(...skipping 12 matching lines...) Expand all Loading... | |
156 // we could avoid maintaining a friends list here. | 195 // we could avoid maintaining a friends list here. |
157 friend class BluetoothAPI; | 196 friend class BluetoothAPI; |
158 friend class api::BluetoothSocketApiFunction; | 197 friend class api::BluetoothSocketApiFunction; |
159 friend class api::BluetoothSocketEventDispatcher; | 198 friend class api::BluetoothSocketEventDispatcher; |
160 friend class core_api::SerialEventDispatcher; | 199 friend class core_api::SerialEventDispatcher; |
161 friend class core_api::TCPServerSocketEventDispatcher; | 200 friend class core_api::TCPServerSocketEventDispatcher; |
162 friend class core_api::TCPSocketEventDispatcher; | 201 friend class core_api::TCPSocketEventDispatcher; |
163 friend class core_api::UDPSocketEventDispatcher; | 202 friend class core_api::UDPSocketEventDispatcher; |
164 friend class BrowserContextKeyedAPIFactory<ApiResourceManager<T> >; | 203 friend class BrowserContextKeyedAPIFactory<ApiResourceManager<T> >; |
165 | 204 |
166 // BrowserContextKeyedAPI implementation. | |
167 static const char* service_name() { return T::service_name(); } | |
168 | |
169 static const bool kServiceHasOwnInstanceInIncognito = true; | 205 static const bool kServiceHasOwnInstanceInIncognito = true; |
170 static const bool kServiceIsNULLWhileTesting = true; | 206 static const bool kServiceIsNULLWhileTesting = true; |
171 | 207 |
172 // ApiResourceData class handles resource bookkeeping on a thread | 208 // ApiResourceData class handles resource bookkeeping on a thread |
173 // where resource lifetime is handled. | 209 // where resource lifetime is handled. |
174 class ApiResourceData : public base::RefCountedThreadSafe<ApiResourceData> { | 210 class ApiResourceData : public base::RefCountedThreadSafe<ApiResourceData> { |
175 public: | 211 public: |
176 typedef std::map<int, linked_ptr<T> > ApiResourceMap; | 212 typedef std::map<int, linked_ptr<T> > ApiResourceMap; |
177 // Lookup map from extension id's to allocated resource id's. | 213 // Lookup map from extension id's to allocated resource id's. |
178 typedef std::map<std::string, base::hash_set<int> > ExtensionToResourceMap; | 214 typedef std::map<std::string, base::hash_set<int> > ExtensionToResourceMap; |
179 | 215 |
180 explicit ApiResourceData(const content::BrowserThread::ID thread_id) | 216 ApiResourceData() : next_id_(1) {} |
181 : next_id_(1), thread_id_(thread_id) {} | |
182 | 217 |
183 int Add(T* api_resource) { | 218 int Add(T* api_resource) { |
184 DCHECK_CURRENTLY_ON(thread_id_); | 219 DCHECK(ThreadingTraits::IsCalledOnValidThread()); |
185 int id = GenerateId(); | 220 int id = GenerateId(); |
186 if (id > 0) { | 221 if (id > 0) { |
187 linked_ptr<T> resource_ptr(api_resource); | 222 linked_ptr<T> resource_ptr(api_resource); |
188 api_resource_map_[id] = resource_ptr; | 223 api_resource_map_[id] = resource_ptr; |
189 | 224 |
190 const std::string& extension_id = api_resource->owner_extension_id(); | 225 const std::string& extension_id = api_resource->owner_extension_id(); |
191 if (extension_resource_map_.find(extension_id) == | 226 if (extension_resource_map_.find(extension_id) == |
192 extension_resource_map_.end()) { | 227 extension_resource_map_.end()) { |
193 extension_resource_map_[extension_id] = base::hash_set<int>(); | 228 extension_resource_map_[extension_id] = base::hash_set<int>(); |
194 } | 229 } |
195 extension_resource_map_[extension_id].insert(id); | 230 extension_resource_map_[extension_id].insert(id); |
196 | 231 |
197 return id; | 232 return id; |
198 } | 233 } |
199 return 0; | 234 return 0; |
200 } | 235 } |
201 | 236 |
202 void Remove(const std::string& extension_id, int api_resource_id) { | 237 void Remove(const std::string& extension_id, int api_resource_id) { |
203 DCHECK_CURRENTLY_ON(thread_id_); | 238 DCHECK(ThreadingTraits::IsCalledOnValidThread()); |
204 if (GetOwnedResource(extension_id, api_resource_id) != NULL) { | 239 if (GetOwnedResource(extension_id, api_resource_id) != NULL) { |
205 DCHECK(extension_resource_map_.find(extension_id) != | 240 DCHECK(extension_resource_map_.find(extension_id) != |
206 extension_resource_map_.end()); | 241 extension_resource_map_.end()); |
207 extension_resource_map_[extension_id].erase(api_resource_id); | 242 extension_resource_map_[extension_id].erase(api_resource_id); |
208 api_resource_map_.erase(api_resource_id); | 243 api_resource_map_.erase(api_resource_id); |
209 } | 244 } |
210 } | 245 } |
211 | 246 |
212 T* Get(const std::string& extension_id, int api_resource_id) { | 247 T* Get(const std::string& extension_id, int api_resource_id) { |
213 DCHECK_CURRENTLY_ON(thread_id_); | 248 DCHECK(ThreadingTraits::IsCalledOnValidThread()); |
214 return GetOwnedResource(extension_id, api_resource_id); | 249 return GetOwnedResource(extension_id, api_resource_id); |
215 } | 250 } |
216 | 251 |
217 base::hash_set<int>* GetResourceIds(const std::string& extension_id) { | 252 base::hash_set<int>* GetResourceIds(const std::string& extension_id) { |
218 DCHECK_CURRENTLY_ON(thread_id_); | 253 DCHECK(ThreadingTraits::IsCalledOnValidThread()); |
219 return GetOwnedResourceIds(extension_id); | 254 return GetOwnedResourceIds(extension_id); |
220 } | 255 } |
221 | 256 |
222 void InitiateExtensionUnloadedCleanup(const std::string& extension_id) { | 257 void InitiateExtensionUnloadedCleanup(const std::string& extension_id) { |
223 if (content::BrowserThread::CurrentlyOn(thread_id_)) { | 258 if (ThreadingTraits::IsCalledOnValidThread()) { |
224 CleanupResourcesFromUnloadedExtension(extension_id); | 259 CleanupResourcesFromUnloadedExtension(extension_id); |
225 } else { | 260 } else { |
226 content::BrowserThread::PostTask( | 261 ThreadingTraits::GetSequencedTaskRunner()->PostTask( |
227 thread_id_, | |
228 FROM_HERE, | 262 FROM_HERE, |
229 base::Bind(&ApiResourceData::CleanupResourcesFromUnloadedExtension, | 263 base::Bind(&ApiResourceData::CleanupResourcesFromUnloadedExtension, |
230 this, | 264 this, |
231 extension_id)); | 265 extension_id)); |
232 } | 266 } |
233 } | 267 } |
234 | 268 |
235 void InitiateExtensionSuspendedCleanup(const std::string& extension_id) { | 269 void InitiateExtensionSuspendedCleanup(const std::string& extension_id) { |
236 if (content::BrowserThread::CurrentlyOn(thread_id_)) { | 270 if (ThreadingTraits::IsCalledOnValidThread()) { |
237 CleanupResourcesFromSuspendedExtension(extension_id); | 271 CleanupResourcesFromSuspendedExtension(extension_id); |
238 } else { | 272 } else { |
239 content::BrowserThread::PostTask( | 273 ThreadingTraits::GetSequencedTaskRunner()->PostTask( |
240 thread_id_, | |
241 FROM_HERE, | 274 FROM_HERE, |
242 base::Bind(&ApiResourceData::CleanupResourcesFromSuspendedExtension, | 275 base::Bind(&ApiResourceData::CleanupResourcesFromSuspendedExtension, |
243 this, | 276 this, |
244 extension_id)); | 277 extension_id)); |
245 } | 278 } |
246 } | 279 } |
247 | 280 |
248 void InititateCleanup() { | 281 void InititateCleanup() { |
249 if (content::BrowserThread::CurrentlyOn(thread_id_)) { | 282 if (ThreadingTraits::IsCalledOnValidThread()) { |
250 Cleanup(); | 283 Cleanup(); |
251 } else { | 284 } else { |
252 content::BrowserThread::PostTask( | 285 ThreadingTraits::GetSequencedTaskRunner()->PostTask( |
253 thread_id_, FROM_HERE, base::Bind(&ApiResourceData::Cleanup, this)); | 286 FROM_HERE, base::Bind(&ApiResourceData::Cleanup, this)); |
254 } | 287 } |
255 } | 288 } |
256 | 289 |
257 private: | 290 private: |
258 friend class base::RefCountedThreadSafe<ApiResourceData>; | 291 friend class base::RefCountedThreadSafe<ApiResourceData>; |
259 | 292 |
260 virtual ~ApiResourceData() {} | 293 virtual ~ApiResourceData() {} |
261 | 294 |
262 T* GetOwnedResource(const std::string& extension_id, int api_resource_id) { | 295 T* GetOwnedResource(const std::string& extension_id, int api_resource_id) { |
263 linked_ptr<T> ptr = api_resource_map_[api_resource_id]; | 296 linked_ptr<T> ptr = api_resource_map_[api_resource_id]; |
264 T* resource = ptr.get(); | 297 T* resource = ptr.get(); |
265 if (resource && extension_id == resource->owner_extension_id()) | 298 if (resource && extension_id == resource->owner_extension_id()) |
266 return resource; | 299 return resource; |
267 return NULL; | 300 return NULL; |
268 } | 301 } |
269 | 302 |
270 base::hash_set<int>* GetOwnedResourceIds(const std::string& extension_id) { | 303 base::hash_set<int>* GetOwnedResourceIds(const std::string& extension_id) { |
271 DCHECK_CURRENTLY_ON(thread_id_); | 304 DCHECK(ThreadingTraits::IsCalledOnValidThread()); |
272 if (extension_resource_map_.find(extension_id) == | 305 if (extension_resource_map_.find(extension_id) == |
273 extension_resource_map_.end()) | 306 extension_resource_map_.end()) |
274 return NULL; | 307 return NULL; |
275 | 308 |
276 return &extension_resource_map_[extension_id]; | 309 return &extension_resource_map_[extension_id]; |
277 } | 310 } |
278 | 311 |
279 void CleanupResourcesFromUnloadedExtension( | 312 void CleanupResourcesFromUnloadedExtension( |
280 const std::string& extension_id) { | 313 const std::string& extension_id) { |
281 CleanupResourcesFromExtension(extension_id, true); | 314 CleanupResourcesFromExtension(extension_id, true); |
282 } | 315 } |
283 | 316 |
284 void CleanupResourcesFromSuspendedExtension( | 317 void CleanupResourcesFromSuspendedExtension( |
285 const std::string& extension_id) { | 318 const std::string& extension_id) { |
286 CleanupResourcesFromExtension(extension_id, false); | 319 CleanupResourcesFromExtension(extension_id, false); |
287 } | 320 } |
288 | 321 |
289 void CleanupResourcesFromExtension(const std::string& extension_id, | 322 void CleanupResourcesFromExtension(const std::string& extension_id, |
290 bool remove_all) { | 323 bool remove_all) { |
291 DCHECK_CURRENTLY_ON(thread_id_); | 324 DCHECK(ThreadingTraits::IsCalledOnValidThread()); |
292 | 325 |
293 if (extension_resource_map_.find(extension_id) == | 326 if (extension_resource_map_.find(extension_id) == |
294 extension_resource_map_.end()) { | 327 extension_resource_map_.end()) { |
295 return; | 328 return; |
296 } | 329 } |
297 | 330 |
298 // Remove all resources, or the non persistent ones only if |remove_all| | 331 // Remove all resources, or the non persistent ones only if |remove_all| |
299 // is false. | 332 // is false. |
300 base::hash_set<int>& resource_ids = extension_resource_map_[extension_id]; | 333 base::hash_set<int>& resource_ids = extension_resource_map_[extension_id]; |
301 for (base::hash_set<int>::iterator it = resource_ids.begin(); | 334 for (base::hash_set<int>::iterator it = resource_ids.begin(); |
(...skipping 15 matching lines...) Expand all Loading... | |
317 } | 350 } |
318 } // end for | 351 } // end for |
319 | 352 |
320 // Remove extension entry if we removed all its resources. | 353 // Remove extension entry if we removed all its resources. |
321 if (resource_ids.size() == 0) { | 354 if (resource_ids.size() == 0) { |
322 extension_resource_map_.erase(extension_id); | 355 extension_resource_map_.erase(extension_id); |
323 } | 356 } |
324 } | 357 } |
325 | 358 |
326 void Cleanup() { | 359 void Cleanup() { |
327 DCHECK_CURRENTLY_ON(thread_id_); | 360 DCHECK(ThreadingTraits::IsCalledOnValidThread()); |
328 | 361 |
329 api_resource_map_.clear(); | 362 api_resource_map_.clear(); |
330 extension_resource_map_.clear(); | 363 extension_resource_map_.clear(); |
331 } | 364 } |
332 | 365 |
333 int GenerateId() { return next_id_++; } | 366 int GenerateId() { return next_id_++; } |
334 | 367 |
335 int next_id_; | 368 int next_id_; |
336 const content::BrowserThread::ID thread_id_; | |
337 ApiResourceMap api_resource_map_; | 369 ApiResourceMap api_resource_map_; |
338 ExtensionToResourceMap extension_resource_map_; | 370 ExtensionToResourceMap extension_resource_map_; |
339 }; | 371 }; |
340 | 372 |
341 content::BrowserThread::ID thread_id_; | |
342 content::NotificationRegistrar registrar_; | 373 content::NotificationRegistrar registrar_; |
343 scoped_refptr<ApiResourceData> data_; | 374 scoped_refptr<ApiResourceData> data_; |
344 }; | 375 }; |
345 | 376 |
377 // With WorkerPoolThreadTraits, ApiResourceManager can be used to manage the | |
378 // lifetime of a set of resources that live on sequenced task runner threads | |
379 // which ApiFunctions use. Examples of such resources are temporary file | |
380 // resources produced by certain API calls. | |
381 // | |
382 // Instead of kThreadId. classes used for tracking identifying such resources | |
Ken Rockot(use gerrit already)
2014/07/22 15:33:59
nit: -identifying? (or +and)
zel
2014/07/22 22:45:03
Done.
| |
383 // should define kSequenceToken and kShutdownBehavior to identify sequence task | |
384 // runner for ApiResourceManager to work on and how pending tasks should behave | |
385 // on shutdown. | |
386 // The user must also define a static const char* service_name() that returns | |
387 // the name of the service, and in order for ApiWorkerPoolResourceManager to use | |
388 // service_name() friend this class. | |
389 // | |
390 // In the cc file the user must define a GetFactoryInstance() and manage their | |
391 // own instances (typically using LazyInstance or Singleton). | |
392 // | |
393 // E.g.: | |
394 // | |
395 // class PoolResource { | |
396 // public: | |
397 // static const char kSequenceToken[] = "temp_files"; | |
398 // static const base::SequencedWorkerPool::WorkerShutdown kShutdownBehavior = | |
399 // base::SequencedWorkerPool::BLOCK_SHUTDOWN; | |
400 // private: | |
401 // friend class ApiResourceManager<WorkerPoolResource, | |
402 // WorkerPoolThreadTraits>; | |
403 // static const char* service_name() { | |
404 // return "TempFilesResourceManager"; | |
405 // } | |
406 // }; | |
407 // | |
408 // In the cc file: | |
409 // | |
410 // static base::LazyInstance<BrowserContextKeyedAPIFactory< | |
411 // ApiResourceManager<Resource, WorkerPoolThreadTraits> > > | |
412 // g_factory = LAZY_INSTANCE_INITIALIZER; | |
413 // | |
414 // | |
415 // template <> | |
416 // BrowserContextKeyedAPIFactory<ApiResourceManager<WorkerPoolResource> >* | |
417 // ApiResourceManager<WorkerPoolPoolResource, | |
418 // WorkerPoolThreadTraits>::GetFactoryInstance() { | |
419 // return g_factory.Pointer(); | |
420 // } | |
421 template <typename T> | |
422 struct WorkerPoolThreadTraits { | |
423 static bool IsCalledOnValidThread() { | |
424 return content::BrowserThread::GetBlockingPool() | |
425 ->IsRunningSequenceOnCurrentThread( | |
426 content::BrowserThread::GetBlockingPool()->GetNamedSequenceToken( | |
427 T::kSequenceToken)); | |
428 } | |
429 | |
430 static bool IsMessageLoopValid() { | |
431 return content::BrowserThread::GetBlockingPool() != NULL; | |
432 } | |
433 | |
434 static scoped_refptr<base::SequencedTaskRunner> GetSequencedTaskRunner() { | |
435 return content::BrowserThread::GetBlockingPool() | |
436 ->GetSequencedTaskRunnerWithShutdownBehavior( | |
437 content::BrowserThread::GetBlockingPool()->GetNamedSequenceToken( | |
438 T::kSequenceToken), | |
439 T::kShutdownBehavior); | |
440 } | |
441 }; | |
442 | |
346 } // namespace extensions | 443 } // namespace extensions |
347 | 444 |
348 #endif // EXTENSIONS_BROWSER_API_API_RESOURCE_MANAGER_H_ | 445 #endif // EXTENSIONS_BROWSER_API_API_RESOURCE_MANAGER_H_ |
OLD | NEW |