Chromium Code Reviews| 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 |