OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 // MediaFileSystemRegistry implementation. | 5 // MediaFileSystemRegistry implementation. |
6 | 6 |
7 #include "chrome/browser/media_gallery/media_file_system_registry.h" | 7 #include "chrome/browser/media_gallery/media_file_system_registry.h" |
8 | 8 |
9 #include <set> | 9 #include <set> |
10 #include <vector> | 10 #include <vector> |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
119 const FilePath& fs_path, | 119 const FilePath& fs_path, |
120 const std::string& filesystem_id) | 120 const std::string& filesystem_id) |
121 : name(fs_name), | 121 : name(fs_name), |
122 path(fs_path), | 122 path(fs_path), |
123 fsid(filesystem_id) { | 123 fsid(filesystem_id) { |
124 } | 124 } |
125 | 125 |
126 MediaFileSystemInfo::MediaFileSystemInfo() {} | 126 MediaFileSystemInfo::MediaFileSystemInfo() {} |
127 | 127 |
128 #if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) | 128 #if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) |
129 // Class to manage MTPDeviceDelegateImpl object for the attached MTP device. | |
130 // Refcounted to reuse the same MTP device delegate entry across extensions. | |
131 // This class supports WeakPtr (extends SupportsWeakPtr) to expose itself as | |
132 // a weak pointer to MediaFileSystemRegistry. | |
133 class ScopedMTPDeviceMapEntry | |
134 : public base::RefCounted<ScopedMTPDeviceMapEntry>, | |
135 public base::SupportsWeakPtr<ScopedMTPDeviceMapEntry> { | |
136 public: | |
137 // |no_references_callback| is called when the last ScopedMTPDeviceMapEntry | |
138 // reference goes away. | |
139 ScopedMTPDeviceMapEntry(const FilePath::StringType& device_location, | |
140 const base::Closure& no_references_callback) | |
141 : device_location_(device_location), | |
142 no_references_callback_(no_references_callback) { | |
143 BrowserThread::PostTask( | |
144 BrowserThread::IO, FROM_HERE, | |
145 Bind(&MTPDeviceMapService::AddDelegate, | |
146 base::Unretained(MTPDeviceMapService::GetInstance()), | |
147 device_location_, | |
148 make_scoped_refptr(new MTPDeviceDelegateImpl(device_location)))); | |
149 } | |
150 | 129 |
151 private: | 130 ScopedMTPDeviceMapEntry::ScopedMTPDeviceMapEntry( |
152 // Friend declaration for ref counted implementation. | 131 const FilePath::StringType& device_location, |
153 friend class base::RefCounted<ScopedMTPDeviceMapEntry>; | 132 const base::Closure& no_references_callback) |
133 : device_location_(device_location), | |
134 delegate_(new MTPDeviceDelegateImpl(device_location)), | |
135 no_references_callback_(no_references_callback) { | |
136 DCHECK(delegate_); | |
Lei Zhang
2012/11/09 09:14:53
No need to check for OOM conditions
vandebo (ex-Chrome)
2012/11/13 06:50:18
Done.
| |
137 BrowserThread::PostTask( | |
138 BrowserThread::IO, FROM_HERE, | |
139 Bind(&MTPDeviceMapService::AddDelegate, | |
140 base::Unretained(MTPDeviceMapService::GetInstance()), | |
141 device_location_, make_scoped_refptr(delegate_))); | |
142 } | |
154 | 143 |
155 // Private because this class is ref-counted. | 144 ScopedMTPDeviceMapEntry::~ScopedMTPDeviceMapEntry() { |
156 ~ScopedMTPDeviceMapEntry() { | 145 BrowserThread::PostTask( |
157 BrowserThread::PostTask( | 146 BrowserThread::IO, FROM_HERE, |
158 BrowserThread::IO, FROM_HERE, | 147 Bind(&MTPDeviceMapService::RemoveDelegate, |
159 Bind(&MTPDeviceMapService::RemoveDelegate, | 148 base::Unretained(MTPDeviceMapService::GetInstance()), |
160 base::Unretained(MTPDeviceMapService::GetInstance()), | 149 device_location_)); |
161 device_location_)); | 150 no_references_callback_.Run(); |
162 no_references_callback_.Run(); | 151 } |
163 } | |
164 | 152 |
165 // Store the MTP or PTP device location. | 153 #endif // defined(SUPPORT_MTP_DEVICE_FILESYSTEM) |
166 const FilePath::StringType device_location_; | |
167 | |
168 // A callback to call when the last reference of this object goes away. | |
169 base::Closure no_references_callback_; | |
170 | |
171 DISALLOW_COPY_AND_ASSIGN(ScopedMTPDeviceMapEntry); | |
172 }; | |
173 #endif | |
174 | 154 |
175 // The main owner of this class is | 155 // The main owner of this class is |
176 // |MediaFileSystemRegistry::extension_hosts_map_|, but a callback may | 156 // |MediaFileSystemRegistry::extension_hosts_map_|, but a callback may |
177 // temporarily hold a reference. | 157 // temporarily hold a reference. |
178 class ExtensionGalleriesHost | 158 class ExtensionGalleriesHost |
179 : public base::RefCountedThreadSafe<ExtensionGalleriesHost>, | 159 : public base::RefCountedThreadSafe<ExtensionGalleriesHost>, |
180 public content::NotificationObserver { | 160 public content::NotificationObserver { |
181 public: | 161 public: |
182 // |no_references_callback| is called when the last RenderViewHost reference | 162 // |no_references_callback| is called when the last RenderViewHost reference |
183 // goes away. RenderViewHost references are added through ReferenceFromRVH(). | 163 // goes away. RenderViewHost references are added through ReferenceFromRVH(). |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
238 | 218 |
239 file_system_context_->RevokeFileSystem(gallery->second.fsid); | 219 file_system_context_->RevokeFileSystem(gallery->second.fsid); |
240 pref_id_map_.erase(gallery); | 220 pref_id_map_.erase(gallery); |
241 | 221 |
242 #if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) | 222 #if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) |
243 MediaDeviceEntryReferencesMap::iterator mtp_device_host = | 223 MediaDeviceEntryReferencesMap::iterator mtp_device_host = |
244 media_device_map_references_.find(id); | 224 media_device_map_references_.find(id); |
245 if (mtp_device_host != media_device_map_references_.end()) | 225 if (mtp_device_host != media_device_map_references_.end()) |
246 media_device_map_references_.erase(mtp_device_host); | 226 media_device_map_references_.erase(mtp_device_host); |
247 #endif | 227 #endif |
228 | |
229 if (pref_id_map_.empty()) { | |
230 rph_refs_.clear(); | |
231 CleanUp(); | |
232 } | |
248 } | 233 } |
249 | 234 |
250 // Indicate that the passed |rvh| will reference the file system ids created | 235 // Indicate that the passed |rvh| will reference the file system ids created |
251 // by this class. It is safe to call this multiple times with the same RVH. | 236 // by this class. It is safe to call this multiple times with the same RVH. |
252 void ReferenceFromRVH(const content::RenderViewHost* rvh) { | 237 void ReferenceFromRVH(const content::RenderViewHost* rvh) { |
253 WebContents* contents = WebContents::FromRenderViewHost(rvh); | 238 WebContents* contents = WebContents::FromRenderViewHost(rvh); |
254 if (registrar_.IsRegistered(this, | 239 if (registrar_.IsRegistered(this, |
255 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 240 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
256 content::Source<WebContents>(contents))) { | 241 content::Source<WebContents>(contents))) { |
257 return; | 242 return; |
258 } | 243 } |
259 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 244 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
260 content::Source<WebContents>(contents)); | 245 content::Source<WebContents>(contents)); |
261 registrar_.Add( | 246 registrar_.Add( |
262 this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 247 this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
263 content::Source<NavigationController>(&contents->GetController())); | 248 content::Source<NavigationController>(&contents->GetController())); |
264 | 249 |
265 RenderProcessHost* rph = contents->GetRenderProcessHost(); | 250 RenderProcessHost* rph = contents->GetRenderProcessHost(); |
266 rph_refs_[rph].insert(contents); | 251 rph_refs_[rph].insert(contents); |
267 if (rph_refs_[rph].size() == 1) { | 252 if (rph_refs_[rph].size() == 1) { |
268 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | 253 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
269 content::Source<RenderProcessHost>(rph)); | 254 content::Source<RenderProcessHost>(rph)); |
270 } | 255 } |
271 } | 256 } |
272 | 257 |
273 private: | 258 private: |
274 typedef std::map<MediaGalleryPrefId, MediaFileSystemInfo> | 259 typedef std::map<MediaGalleryPrefId, MediaFileSystemInfo> |
275 PrefIdFsInfoMap; | 260 PrefIdFsInfoMap; |
276 #if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) | 261 #if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) |
277 typedef std::map<MediaGalleryPrefId, | 262 typedef std::map<MediaGalleryPrefId, |
278 scoped_refptr<ScopedMTPDeviceMapEntry> > | 263 scoped_refptr<ScopedMTPDeviceMapEntry> > |
(...skipping 12 matching lines...) Expand all Loading... | |
291 #if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) | 276 #if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) |
292 DCHECK(media_device_map_references_.empty()); | 277 DCHECK(media_device_map_references_.empty()); |
293 #endif | 278 #endif |
294 } | 279 } |
295 | 280 |
296 // NotificationObserver implementation. | 281 // NotificationObserver implementation. |
297 virtual void Observe(int type, | 282 virtual void Observe(int type, |
298 const content::NotificationSource& source, | 283 const content::NotificationSource& source, |
299 const content::NotificationDetails& details) OVERRIDE { | 284 const content::NotificationDetails& details) OVERRIDE { |
300 switch (type) { | 285 switch (type) { |
301 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { | 286 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: { |
302 OnRendererProcessClosed( | 287 OnRendererProcessTerminated( |
303 content::Source<RenderProcessHost>(source).ptr()); | 288 content::Source<RenderProcessHost>(source).ptr()); |
304 break; | 289 break; |
305 } | 290 } |
306 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { | 291 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { |
307 OnWebContentsDestroyedOrNavigated( | 292 OnWebContentsDestroyedOrNavigated( |
308 content::Source<WebContents>(source).ptr()); | 293 content::Source<WebContents>(source).ptr()); |
309 break; | 294 break; |
310 } | 295 } |
311 case content::NOTIFICATION_NAV_ENTRY_COMMITTED: { | 296 case content::NOTIFICATION_NAV_ENTRY_COMMITTED: { |
312 NavigationController* controller = | 297 NavigationController* controller = |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
374 MakeJSONFileSystemName(gallery_info.display_name, | 359 MakeJSONFileSystemName(gallery_info.display_name, |
375 pref_id, | 360 pref_id, |
376 GetTransientIdForRemovableDeviceId(device_id)), | 361 GetTransientIdForRemovableDeviceId(device_id)), |
377 path, | 362 path, |
378 fsid); | 363 fsid); |
379 result.push_back(new_entry); | 364 result.push_back(new_entry); |
380 new_galleries.insert(pref_id); | 365 new_galleries.insert(pref_id); |
381 pref_id_map_[pref_id] = new_entry; | 366 pref_id_map_[pref_id] = new_entry; |
382 } | 367 } |
383 | 368 |
384 RevokeOldGalleries(new_galleries); | 369 if (result.size() == 0) { |
370 rph_refs_.clear(); | |
371 CleanUp(); | |
372 } else { | |
373 RevokeOldGalleries(new_galleries); | |
374 } | |
385 | 375 |
386 callback.Run(result); | 376 callback.Run(result); |
387 } | 377 } |
388 | 378 |
389 void OnRendererProcessClosed(const RenderProcessHost* rph) { | 379 void OnRendererProcessTerminated(const RenderProcessHost* rph) { |
390 RenderProcessHostRefCount::const_iterator rph_info = rph_refs_.find(rph); | 380 RenderProcessHostRefCount::const_iterator rph_info = rph_refs_.find(rph); |
391 DCHECK(rph_info != rph_refs_.end()); | 381 DCHECK(rph_info != rph_refs_.end()); |
392 // We're going to remove everything from the set, so we make a copy | 382 // We're going to remove everything from the set, so we make a copy |
393 // before operating on it. | 383 // before operating on it. |
394 std::set<const WebContents*> closed_web_contents = rph_info->second; | 384 std::set<const WebContents*> closed_web_contents = rph_info->second; |
395 DCHECK(!closed_web_contents.empty()); | 385 DCHECK(!closed_web_contents.empty()); |
396 | 386 |
397 for (std::set<const WebContents*>::const_iterator it = | 387 for (std::set<const WebContents*>::const_iterator it = |
398 closed_web_contents.begin(); | 388 closed_web_contents.begin(); |
399 it != closed_web_contents.end(); | 389 it != closed_web_contents.end(); |
400 ++it) { | 390 ++it) { |
401 OnWebContentsDestroyedOrNavigated(*it); | 391 OnWebContentsDestroyedOrNavigated(*it); |
402 } | 392 } |
403 } | 393 } |
404 | 394 |
405 void OnWebContentsDestroyedOrNavigated(const WebContents* contents) { | 395 void OnWebContentsDestroyedOrNavigated(const WebContents* contents) { |
406 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 396 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
407 content::Source<WebContents>(contents)); | 397 content::Source<WebContents>(contents)); |
408 registrar_.Remove( | 398 registrar_.Remove( |
409 this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 399 this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
410 content::Source<NavigationController>(&contents->GetController())); | 400 content::Source<NavigationController>(&contents->GetController())); |
411 | 401 |
412 RenderProcessHost* rph = contents->GetRenderProcessHost(); | 402 RenderProcessHost* rph = contents->GetRenderProcessHost(); |
413 RenderProcessHostRefCount::iterator process_refs = rph_refs_.find(rph); | 403 RenderProcessHostRefCount::iterator process_refs = rph_refs_.find(rph); |
414 DCHECK(process_refs != rph_refs_.end()); | 404 DCHECK(process_refs != rph_refs_.end()); |
415 process_refs->second.erase(contents); | 405 process_refs->second.erase(contents); |
416 if (process_refs->second.empty()) { | 406 if (process_refs->second.empty()) { |
417 registrar_.Remove(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | 407 registrar_.Remove(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
418 content::Source<RenderProcessHost>(rph)); | 408 content::Source<RenderProcessHost>(rph)); |
419 rph_refs_.erase(process_refs); | 409 rph_refs_.erase(process_refs); |
420 } | 410 } |
421 | 411 |
422 if (rph_refs_.empty()) { | 412 if (rph_refs_.empty()) |
423 for (PrefIdFsInfoMap::const_iterator it = pref_id_map_.begin(); | 413 CleanUp(); |
424 it != pref_id_map_.end(); | 414 } |
425 ++it) { | 415 |
426 file_system_context_->RevokeFileSystem(it->second.fsid); | 416 void CleanUp() { |
427 } | 417 DCHECK(rph_refs_.empty()); |
428 pref_id_map_.clear(); | 418 for (PrefIdFsInfoMap::const_iterator it = pref_id_map_.begin(); |
419 it != pref_id_map_.end(); | |
420 ++it) { | |
421 file_system_context_->RevokeFileSystem(it->second.fsid); | |
422 } | |
423 pref_id_map_.clear(); | |
429 | 424 |
430 #if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) | 425 #if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) |
431 media_device_map_references_.clear(); | 426 media_device_map_references_.clear(); |
432 #endif | 427 #endif |
433 | 428 |
434 no_references_callback_.Run(); | 429 registrar_.RemoveAll(); |
435 } | 430 |
431 no_references_callback_.Run(); | |
436 } | 432 } |
437 | 433 |
438 // MediaFileSystemRegistry owns |this| and |file_system_context_|, so it's | 434 // MediaFileSystemRegistry owns |this| and |file_system_context_|, so it's |
439 // safe to store a raw pointer. | 435 // safe to store a raw pointer. |
440 MediaFileSystemContext* file_system_context_; | 436 MediaFileSystemContext* file_system_context_; |
441 | 437 |
442 // A callback to call when the last RVH reference goes away. | 438 // A callback to call when the last RVH reference goes away. |
443 base::Closure no_references_callback_; | 439 base::Closure no_references_callback_; |
444 | 440 |
445 // A map from the gallery preferences id to the file system information. | 441 // A map from the gallery preferences id to the file system information. |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
542 | 538 |
543 for (ExtensionGalleriesHostMap::iterator profile_it = | 539 for (ExtensionGalleriesHostMap::iterator profile_it = |
544 extension_hosts_map_.begin(); | 540 extension_hosts_map_.begin(); |
545 profile_it != extension_hosts_map_.end(); | 541 profile_it != extension_hosts_map_.end(); |
546 ++profile_it) { | 542 ++profile_it) { |
547 MediaGalleriesPreferences* preferences = GetPreferences(profile_it->first); | 543 MediaGalleriesPreferences* preferences = GetPreferences(profile_it->first); |
548 preferences->AddGallery(id, name, FilePath(), false /*not user added*/); | 544 preferences->AddGallery(id, name, FilePath(), false /*not user added*/); |
549 } | 545 } |
550 } | 546 } |
551 | 547 |
548 size_t MediaFileSystemRegistry::GetExtensionHostCountForTests() { | |
549 return extension_hosts_map_.size(); | |
550 } | |
551 | |
552 void MediaFileSystemRegistry::OnRemovableStorageDetached( | 552 void MediaFileSystemRegistry::OnRemovableStorageDetached( |
553 const std::string& id) { | 553 const std::string& id) { |
554 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 554 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
555 | 555 |
556 // Since revoking a gallery in the ExtensionGalleriesHost may cause it | 556 // Since revoking a gallery in the ExtensionGalleriesHost may cause it |
557 // to be removed from the map and therefore invalidate any iterator pointing | 557 // to be removed from the map and therefore invalidate any iterator pointing |
558 // to it, this code first copies all the invalid gallery ids and the | 558 // to it, this code first copies all the invalid gallery ids and the |
559 // extension hosts in which they may appear (per profile) and revoked it in | 559 // extension hosts in which they may appear (per profile) and revoked it in |
560 // a second step. | 560 // a second step. |
561 std::vector<InvalidatedGalleriesInfo> invalid_galleries_info; | 561 std::vector<InvalidatedGalleriesInfo> invalid_galleries_info; |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
751 | 751 |
752 PrefChangeRegistrarMap::iterator pref_it = | 752 PrefChangeRegistrarMap::iterator pref_it = |
753 pref_change_registrar_map_.find(profile); | 753 pref_change_registrar_map_.find(profile); |
754 DCHECK(pref_it != pref_change_registrar_map_.end()); | 754 DCHECK(pref_it != pref_change_registrar_map_.end()); |
755 delete pref_it->second; | 755 delete pref_it->second; |
756 pref_change_registrar_map_.erase(pref_it); | 756 pref_change_registrar_map_.erase(pref_it); |
757 } | 757 } |
758 } | 758 } |
759 | 759 |
760 } // namespace chrome | 760 } // namespace chrome |
OLD | NEW |