Index: chrome/browser/media_gallery/media_file_system_registry.cc |
diff --git a/chrome/browser/media_gallery/media_file_system_registry.cc b/chrome/browser/media_gallery/media_file_system_registry.cc |
index c97943dafa9d555e3807737842e9be7424b3c8fa..6bb8e54e5d227c8c1831b0ea6a772d2ac414d4c0 100644 |
--- a/chrome/browser/media_gallery/media_file_system_registry.cc |
+++ b/chrome/browser/media_gallery/media_file_system_registry.cc |
@@ -126,48 +126,36 @@ MediaFileSystemInfo::MediaFileSystemInfo(const std::string& fs_name, |
MediaFileSystemInfo::MediaFileSystemInfo() {} |
#if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) |
-// Class to manage MTPDeviceDelegateImpl object for the attached MTP device. |
-// Refcounted to reuse the same MTP device delegate entry across extensions. |
-// This class supports WeakPtr (extends SupportsWeakPtr) to expose itself as |
-// a weak pointer to MediaFileSystemRegistry. |
-class ScopedMTPDeviceMapEntry |
- : public base::RefCounted<ScopedMTPDeviceMapEntry>, |
- public base::SupportsWeakPtr<ScopedMTPDeviceMapEntry> { |
+// Class to manage the lifetime of MTPDeviceDelegateImpl object for the |
+// attached media transfer protocol (MTP) device. This object is constructed for |
+// each MTP device. |
+class ScopedMTPDeviceMapEntry { |
public: |
- // |no_references_callback| is called when the last ScopedMTPDeviceMapEntry |
- // reference goes away. |
- ScopedMTPDeviceMapEntry(const FilePath::StringType& device_location, |
- const base::Closure& no_references_callback) |
- : device_location_(device_location), |
- no_references_callback_(no_references_callback) { |
+ explicit ScopedMTPDeviceMapEntry(const FilePath::StringType& device_location) |
+ : device_location_(device_location) { |
BrowserThread::PostTask( |
BrowserThread::IO, FROM_HERE, |
Bind(&MTPDeviceMapService::AddDelegate, |
base::Unretained(MTPDeviceMapService::GetInstance()), |
device_location_, |
- make_scoped_refptr(new MTPDeviceDelegateImpl(device_location)))); |
+ new MTPDeviceDelegateImpl(device_location))); |
} |
- private: |
- // Friend declaration for ref counted implementation. |
- friend class base::RefCounted<ScopedMTPDeviceMapEntry>; |
- |
- // Private because this class is ref-counted. |
+ // Destructed when the last user of this MTP device is destroyed or when the |
+ // MTP device is detached from the system or when the browser is in shutdown |
+ // mode or when the extension revokes the MTP device gallery permissions. |
~ScopedMTPDeviceMapEntry() { |
BrowserThread::PostTask( |
BrowserThread::IO, FROM_HERE, |
Bind(&MTPDeviceMapService::RemoveDelegate, |
base::Unretained(MTPDeviceMapService::GetInstance()), |
device_location_)); |
- no_references_callback_.Run(); |
} |
- // Store the MTP or PTP device location. |
+ private: |
+ // The MTP or PTP device location. |
const FilePath::StringType device_location_; |
- // A callback to call when the last reference of this object goes away. |
- base::Closure no_references_callback_; |
- |
DISALLOW_COPY_AND_ASSIGN(ScopedMTPDeviceMapEntry); |
}; |
#endif |
@@ -240,10 +228,19 @@ class ExtensionGalleriesHost |
pref_id_map_.erase(gallery); |
#if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) |
- MediaDeviceEntryReferencesMap::iterator mtp_device_host = |
- media_device_map_references_.find(id); |
- if (mtp_device_host != media_device_map_references_.end()) |
- media_device_map_references_.erase(mtp_device_host); |
+ for (MTPDeviceGalleryReferencesMap::iterator it = |
+ mtp_device_gallery_references_.begin(); |
+ it != mtp_device_gallery_references_.end(); ++it) { |
+ MediaGalleryPrefIdSet::iterator found = it->second.find(id); |
+ if (found == it->second.end()) |
+ continue; |
+ it->second.erase(id); |
+ if (it->second.empty()) { |
+ file_system_context_->RemoveMTPDeviceReferenceForHost(it->first, this); |
+ mtp_device_gallery_references_.erase(it); |
+ } |
+ break; |
+ } |
#endif |
} |
@@ -274,9 +271,8 @@ class ExtensionGalleriesHost |
typedef std::map<MediaGalleryPrefId, MediaFileSystemInfo> |
PrefIdFsInfoMap; |
#if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) |
- typedef std::map<MediaGalleryPrefId, |
- scoped_refptr<ScopedMTPDeviceMapEntry> > |
- MediaDeviceEntryReferencesMap; |
+ typedef std::map<const FilePath::StringType, MediaGalleryPrefIdSet> |
+ MTPDeviceGalleryReferencesMap; |
#endif |
typedef std::map<const RenderProcessHost*, std::set<const WebContents*> > |
RenderProcessHostRefCount; |
@@ -289,7 +285,7 @@ class ExtensionGalleriesHost |
DCHECK(pref_id_map_.empty()); |
#if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) |
- DCHECK(media_device_map_references_.empty()); |
+ DCHECK(mtp_device_gallery_references_.empty()); |
#endif |
} |
@@ -358,11 +354,9 @@ class ExtensionGalleriesHost |
device_id, path); |
} else { |
#if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) |
- scoped_refptr<ScopedMTPDeviceMapEntry> mtp_device_host; |
fsid = file_system_context_->RegisterFileSystemForMTPDevice( |
- device_id, path, &mtp_device_host); |
- DCHECK(mtp_device_host.get()); |
- media_device_map_references_[pref_id] = mtp_device_host; |
+ device_id, path, this); |
+ mtp_device_gallery_references_[path.value()].insert(pref_id); |
#else |
NOTIMPLEMENTED(); |
continue; |
@@ -426,11 +420,14 @@ class ExtensionGalleriesHost |
file_system_context_->RevokeFileSystem(it->second.fsid); |
} |
pref_id_map_.clear(); |
- |
#if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) |
- media_device_map_references_.clear(); |
+ for (MTPDeviceGalleryReferencesMap::iterator it = |
+ mtp_device_gallery_references_.begin(); |
+ it != mtp_device_gallery_references_.end(); ++it) { |
+ file_system_context_->RemoveMTPDeviceReferenceForHost(it->first, this); |
+ } |
+ mtp_device_gallery_references_.clear(); |
#endif |
- |
no_references_callback_.Run(); |
} |
} |
@@ -446,9 +443,9 @@ class ExtensionGalleriesHost |
PrefIdFsInfoMap pref_id_map_; |
#if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) |
- // A map from the gallery preferences id to the corresponding media device |
- // host object. |
- MediaDeviceEntryReferencesMap media_device_map_references_; |
+ // A map from the MTP device id to a set of media galleries that references to |
+ // that device. |
+ MTPDeviceGalleryReferencesMap mtp_device_gallery_references_; |
#endif |
// The set of render processes and web contents that may have references to |
@@ -536,7 +533,6 @@ void MediaFileSystemRegistry::OnRemovableStorageAttached( |
const std::string& id, const string16& name, |
const FilePath::StringType& location) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
if (!MediaStorageUtil::IsMediaDevice(id)) |
return; |
@@ -552,7 +548,6 @@ void MediaFileSystemRegistry::OnRemovableStorageAttached( |
void MediaFileSystemRegistry::OnRemovableStorageDetached( |
const std::string& id) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
// Since revoking a gallery in the ExtensionGalleriesHost may cause it |
// to be removed from the map and therefore invalidate any iterator pointing |
// to it, this code first copies all the invalid gallery ids and the |
@@ -629,7 +624,7 @@ class MediaFileSystemRegistry::MediaFileSystemContextImpl |
#if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) |
virtual std::string RegisterFileSystemForMTPDevice( |
const std::string& device_id, const FilePath& path, |
- scoped_refptr<ScopedMTPDeviceMapEntry>* entry) { |
+ const ExtensionGalleriesHost* galleries_host) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
DCHECK(!MediaStorageUtil::IsMassStorageDevice(device_id)); |
@@ -641,10 +636,17 @@ class MediaFileSystemRegistry::MediaFileSystemContextImpl |
IsolatedContext::GetInstance()->RegisterFileSystemForPath( |
fileapi::kFileSystemTypeDeviceMedia, path, &fs_name); |
CHECK(!fsid.empty()); |
- DCHECK(entry); |
- *entry = registry_->GetOrCreateScopedMTPDeviceMapEntry(path.value()); |
+ registry_->AddGalleriesHostReferenceForMTPDevice(path.value(), |
+ galleries_host); |
return fsid; |
} |
+ |
+ virtual void RemoveMTPDeviceReferenceForHost( |
+ const FilePath::StringType& device_location, |
+ const ExtensionGalleriesHost* galleries_host) { |
+ registry_->RemoveGalleriesHostReferenceForMTPDevice(device_location, |
+ galleries_host); |
+ } |
#endif |
virtual void RevokeFileSystem(const std::string& fsid) { |
@@ -670,6 +672,8 @@ MediaFileSystemRegistry::~MediaFileSystemRegistry() { |
SystemMonitor* system_monitor = SystemMonitor::Get(); |
if (system_monitor) |
system_monitor->RemoveDevicesChangedObserver(this); |
+ DCHECK(mtp_device_delegate_map_.empty()); |
+ DCHECK(mtp_device_references_map_.empty()); |
} |
void MediaFileSystemRegistry::OnPreferenceChanged( |
@@ -712,27 +716,31 @@ void MediaFileSystemRegistry::OnPreferenceChanged( |
} |
#if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) |
-ScopedMTPDeviceMapEntry* |
-MediaFileSystemRegistry::GetOrCreateScopedMTPDeviceMapEntry( |
- const FilePath::StringType& device_location) { |
+void MediaFileSystemRegistry::AddGalleriesHostReferenceForMTPDevice( |
+ const FilePath::StringType& device_location, |
+ const ExtensionGalleriesHost* galleries_host) { |
MTPDeviceDelegateMap::iterator delegate_it = |
- mtp_delegate_map_.find(device_location); |
- if (delegate_it != mtp_delegate_map_.end() && delegate_it->second.get()) |
- return delegate_it->second; |
- ScopedMTPDeviceMapEntry* mtp_device_host = new ScopedMTPDeviceMapEntry( |
- device_location, base::Bind( |
- &MediaFileSystemRegistry::RemoveScopedMTPDeviceMapEntry, |
- base::Unretained(this), device_location)); |
- mtp_delegate_map_[device_location] = mtp_device_host->AsWeakPtr(); |
- return mtp_device_host; |
+ mtp_device_delegate_map_.find(device_location); |
+ if (delegate_it == mtp_device_delegate_map_.end()) { |
+ mtp_device_delegate_map_[device_location] = |
+ new ScopedMTPDeviceMapEntry(device_location); |
+ } |
+ mtp_device_references_map_[device_location].insert(galleries_host); |
} |
-void MediaFileSystemRegistry::RemoveScopedMTPDeviceMapEntry( |
- const FilePath::StringType& device_location) { |
- MTPDeviceDelegateMap::iterator delegate_it = |
- mtp_delegate_map_.find(device_location); |
- DCHECK(delegate_it != mtp_delegate_map_.end()); |
- mtp_delegate_map_.erase(delegate_it); |
+void MediaFileSystemRegistry::RemoveGalleriesHostReferenceForMTPDevice( |
+ const FilePath::StringType& device_location, |
+ const ExtensionGalleriesHost* galleries_host) { |
+ MTPDeviceReferencesMap::iterator hosts_it = |
+ mtp_device_references_map_.find(device_location); |
+ DCHECK(hosts_it != mtp_device_references_map_.end()); |
+ DCHECK(hosts_it->second.find(galleries_host) != hosts_it->second.end()); |
+ hosts_it->second.erase(galleries_host); |
+ if (hosts_it->second.empty()) { |
+ delete mtp_device_delegate_map_[device_location]; |
+ mtp_device_delegate_map_.erase(device_location); |
+ mtp_device_references_map_.erase(hosts_it); |
+ } |
} |
#endif |