Chromium Code Reviews| Index: chrome/browser/media_galleries/media_file_system_registry.cc |
| diff --git a/chrome/browser/media_galleries/media_file_system_registry.cc b/chrome/browser/media_galleries/media_file_system_registry.cc |
| index 1010eb6a1694891baed271dd9b6ecef2eb6122b2..14a4f5737c2ccac07a91d07a6a4faf53db2e74a0 100644 |
| --- a/chrome/browser/media_galleries/media_file_system_registry.cc |
| +++ b/chrome/browser/media_galleries/media_file_system_registry.cc |
| @@ -13,6 +13,7 @@ |
| #include "base/prefs/pref_service.h" |
| #include "base/stl_util.h" |
| #include "chrome/browser/extensions/extension_service.h" |
| +#include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h" |
| #include "chrome/browser/media_galleries/fileapi/mtp_device_map_service.h" |
| #include "chrome/browser/media_galleries/imported_media_gallery_registry.h" |
| #include "chrome/browser/media_galleries/media_file_system_context.h" |
| @@ -36,14 +37,15 @@ |
| #include "extensions/browser/extension_system.h" |
| #include "extensions/common/extension.h" |
| #include "extensions/common/extension_set.h" |
| -#include "webkit/browser/fileapi/isolated_context.h" |
| +#include "webkit/browser/fileapi/external_mount_points.h" |
| +#include "webkit/common/fileapi/file_system_mount_option.h" |
| #include "webkit/common/fileapi/file_system_types.h" |
| using content::BrowserThread; |
| using content::NavigationController; |
| using content::RenderProcessHost; |
| using content::WebContents; |
| -using fileapi::IsolatedContext; |
| +using fileapi::ExternalMountPoints; |
| using storage_monitor::MediaStorageUtil; |
| using storage_monitor::StorageInfo; |
| using storage_monitor::StorageMonitor; |
| @@ -261,15 +263,19 @@ class ExtensionGalleriesHost |
| // |no_references_callback| is called when the last RenderViewHost reference |
| // goes away. RenderViewHost references are added through ReferenceFromRVH(). |
| ExtensionGalleriesHost(MediaFileSystemContext* file_system_context, |
| + const base::FilePath& profile_path, |
| + const std::string& extension_id, |
| const base::Closure& no_references_callback) |
| : file_system_context_(file_system_context), |
| + profile_path_(profile_path), |
| + extension_id_(extension_id), |
| no_references_callback_(no_references_callback), |
| rph_refs_(base::Bind(&ExtensionGalleriesHost::CleanUp, |
| base::Unretained(this))) { |
| } |
| // For each gallery in the list of permitted |galleries|, checks if the |
| - // device is attached and if so looks up or creates a file system id and |
| + // device is attached and if so looks up or creates a file system name and |
| // passes the information needed for the renderer to create those file |
| // system objects to the |callback|. |
| void GetMediaFileSystems(const MediaGalleryPrefIdSet& galleries, |
| @@ -288,6 +294,20 @@ class ExtensionGalleriesHost |
| base::Owned(device_ids), galleries, galleries_info, callback)); |
| } |
| + // Checks if |gallery is attached and if so, registers the file system and |
|
Lei Zhang
2014/03/20 00:46:26
nit: |gallery|
vandebo (ex-Chrome)
2014/03/20 18:08:53
Done.
|
| + // then calls |callback| with the result. |
| + void RegisterMediaFileSystem( |
| + const MediaGalleryPrefInfo& gallery, |
| + const base::Callback<void(base::File::Error result)>& callback) { |
| + // Extract all the device ids so we can make sure they are attached. |
| + MediaStorageUtil::DeviceIdSet* device_ids = |
| + new MediaStorageUtil::DeviceIdSet; |
| + device_ids->insert(gallery.device_id); |
| + MediaStorageUtil::FilterAttachedDevices(device_ids, base::Bind( |
| + &ExtensionGalleriesHost::RegisterAttachedMediaFileSystem, this, |
| + base::Owned(device_ids), gallery, callback)); |
| + } |
| + |
| // Revoke the file system for |id| if this extension has created one for |id|. |
| void RevokeGalleryByPrefId(MediaGalleryPrefId id) { |
| PrefIdFsInfoMap::iterator gallery = pref_id_map_.find(id); |
| @@ -354,18 +374,19 @@ class ExtensionGalleriesHost |
| } |
| base::FilePath path = gallery_info.AbsolutePath(); |
| - if (!MediaStorageUtil::CanCreateFileSystem(device_id, path)) |
| + if (path.empty() || |
| + !MediaStorageUtil::CanCreateFileSystem(device_id, path)) |
| continue; |
| - std::string fsid = |
| - file_system_context_->RegisterFileSystem(device_id, path); |
| - if (fsid.empty()) |
| + std::string fs_name = MediaFileSystemBackend::ConstructMountName( |
| + profile_path_, extension_id_, pref_id); |
| + if (!file_system_context_->RegisterFileSystem(device_id, fs_name, path)) |
| continue; |
| MediaFileSystemInfo new_entry( |
| gallery_info.GetGalleryDisplayName(), |
| - path, |
| - fsid, |
| + file_system_context_->GetRegisteredPath(fs_name), |
| + fs_name, |
| pref_id, |
| GetTransientIdForRemovableDeviceId(device_id), |
| StorageInfo::IsRemovableDevice(device_id), |
| @@ -383,6 +404,47 @@ class ExtensionGalleriesHost |
| callback.Run(result); |
| } |
| + void RegisterAttachedMediaFileSystem( |
| + const MediaStorageUtil::DeviceIdSet* attached_device, |
| + const MediaGalleryPrefInfo& gallery, |
| + const base::Callback<void(base::File::Error result)>& callback) { |
| + base::File::Error result = base::File::FILE_ERROR_NOT_FOUND; |
| + |
| + // If rph_refs is empty then we're actually in the middle of shutdown, and |
| + // Filter...() lagging which can invoke this method interleaved in the |
| + // destruction callback sequence and re-populate pref_id_map_. |
| + if (!attached_device->empty() && !rph_refs_.empty()) { |
| + std::string fs_name = MediaFileSystemBackend::ConstructMountName( |
| + profile_path_, extension_id_, gallery.pref_id); |
| + base::FilePath path = gallery.AbsolutePath(); |
| + const std::string& device_id = gallery.device_id; |
| + |
| + if (ContainsKey(pref_id_map_, gallery.pref_id)) { |
| + result = base::File::FILE_OK; |
| + } else if (!path.empty() && |
| + MediaStorageUtil::CanCreateFileSystem(device_id, path) && |
| + file_system_context_->RegisterFileSystem(device_id, fs_name, |
| + path)) { |
| + result = base::File::FILE_OK; |
| + pref_id_map_[gallery.pref_id] = MediaFileSystemInfo( |
| + gallery.GetGalleryDisplayName(), |
| + file_system_context_->GetRegisteredPath(fs_name), |
| + fs_name, |
| + gallery.pref_id, |
| + GetTransientIdForRemovableDeviceId(device_id), |
| + StorageInfo::IsRemovableDevice(device_id), |
| + StorageInfo::IsMediaDevice(device_id)); |
| + } |
| + } |
| + |
| + if (pref_id_map_.empty()) { |
| + rph_refs_.Reset(); |
| + CleanUp(); |
| + } |
| + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, |
| + base::Bind(callback, result)); |
| + } |
| + |
| std::string GetTransientIdForRemovableDeviceId(const std::string& device_id) { |
| if (!StorageInfo::IsRemovableDevice(device_id)) |
| return std::string(); |
| @@ -406,6 +468,12 @@ class ExtensionGalleriesHost |
| // safe to store a raw pointer. |
| MediaFileSystemContext* file_system_context_; |
| + // Path for the active profile. |
| + base::FilePath profile_path_; |
| + |
| + // Id of the extension this host belongs to. |
| + std::string extension_id_; |
| + |
| // A callback to call when the last RVH reference goes away. |
| base::Closure no_references_callback_; |
| @@ -440,22 +508,9 @@ void MediaFileSystemRegistry::GetMediaFileSystemsForExtension( |
| return; |
| } |
| - ExtensionGalleriesHostMap::iterator extension_hosts = |
| - extension_hosts_map_.find(profile); |
| - if (extension_hosts->second.empty()) |
| - preferences->AddGalleryChangeObserver(this); |
| - |
| ExtensionGalleriesHost* extension_host = |
| - extension_hosts->second[extension->id()].get(); |
| - if (!extension_host) { |
| - extension_host = new ExtensionGalleriesHost( |
| - file_system_context_.get(), |
| - base::Bind(&MediaFileSystemRegistry::OnExtensionGalleriesHostEmpty, |
| - base::Unretained(this), |
| - profile, |
| - extension->id())); |
| - extension_hosts_map_[profile][extension->id()] = extension_host; |
| - } |
| + GetExtensionGalleryHost(profile, preferences, extension->id()); |
| + |
| // This must come before the GetMediaFileSystems call to make sure the |
| // RVH of the context is referenced before the filesystems are retrieved. |
| extension_host->ReferenceFromRVH(rvh); |
| @@ -464,6 +519,39 @@ void MediaFileSystemRegistry::GetMediaFileSystemsForExtension( |
| callback); |
| } |
| +void MediaFileSystemRegistry::RegisterMediaFileSystemForExtension( |
| + const content::RenderViewHost* rvh, |
| + const extensions::Extension* extension, |
| + MediaGalleryPrefId pref_id, |
| + const base::Callback<void(base::File::Error result)>& callback) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + |
| + Profile* profile = |
| + Profile::FromBrowserContext(rvh->GetProcess()->GetBrowserContext()); |
| + MediaGalleriesPreferences* preferences = GetPreferences(profile); |
| + MediaGalleriesPrefInfoMap::const_iterator gallery = |
| + preferences->known_galleries().find(pref_id); |
| + MediaGalleryPrefIdSet permitted_galleries = |
| + preferences->GalleriesForExtension(*extension); |
| + |
| + if (gallery == preferences->known_galleries().end() || |
| + !ContainsKey(permitted_galleries, pref_id)) { |
| + content::BrowserThread::PostTask( |
| + content::BrowserThread::IO, FROM_HERE, |
| + base::Bind(callback, base::File::FILE_ERROR_NOT_FOUND)); |
| + return; |
| + } |
| + |
| + ExtensionGalleriesHost* extension_host = |
| + GetExtensionGalleryHost(profile, preferences, extension->id()); |
| + |
| + // This must come before the GetMediaFileSystems call to make sure the |
| + // RVH of the context is referenced before the filesystems are retrieved. |
| + extension_host->ReferenceFromRVH(rvh); |
| + |
| + extension_host->RegisterMediaFileSystem(gallery->second, callback); |
| +} |
| + |
| MediaGalleriesPreferences* MediaFileSystemRegistry::GetPreferences( |
| Profile* profile) { |
| // Create an empty ExtensionHostMap for this profile on first initialization. |
| @@ -538,41 +626,50 @@ void MediaFileSystemRegistry::OnRemovableStorageDetached( |
| class MediaFileSystemRegistry::MediaFileSystemContextImpl |
| : public MediaFileSystemContext { |
| public: |
| - explicit MediaFileSystemContextImpl(MediaFileSystemRegistry* registry) |
| - : registry_(registry) { |
| - DCHECK(registry_); // Suppresses unused warning on Android. |
| - } |
| + MediaFileSystemContextImpl() {} |
| virtual ~MediaFileSystemContextImpl() {} |
| - virtual std::string RegisterFileSystem( |
| - const std::string& device_id, const base::FilePath& path) OVERRIDE { |
| + virtual bool RegisterFileSystem(const std::string& device_id, |
| + const std::string& fs_name, |
| + const base::FilePath& path) OVERRIDE { |
| if (StorageInfo::IsMassStorageDevice(device_id)) { |
| - return RegisterFileSystemForMassStorage(device_id, path); |
| + return RegisterFileSystemForMassStorage(device_id, fs_name, path); |
| } else { |
| - return RegisterFileSystemForMTPDevice(device_id, path); |
| + return RegisterFileSystemForMTPDevice(device_id, fs_name, path); |
| } |
| } |
| - virtual void RevokeFileSystem(const std::string& fsid) OVERRIDE { |
| + virtual void RevokeFileSystem(const std::string& fs_name) OVERRIDE { |
| ImportedMediaGalleryRegistry* imported_registry = |
| ImportedMediaGalleryRegistry::GetInstance(); |
| - if (imported_registry->RevokeImportedFilesystemOnUIThread(fsid)) |
| + if (imported_registry->RevokeImportedFilesystemOnUIThread(fs_name)) |
| return; |
| - IsolatedContext::GetInstance()->RevokeFileSystem(fsid); |
| + ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(fs_name); |
| content::BrowserThread::PostTask( |
| content::BrowserThread::IO, FROM_HERE, base::Bind( |
| &MTPDeviceMapService::RevokeMTPFileSystem, |
| base::Unretained(MTPDeviceMapService::GetInstance()), |
| - fsid)); |
| + fs_name)); |
| + } |
| + |
| + virtual base::FilePath GetRegisteredPath( |
| + const std::string& fs_name) const OVERRIDE { |
| + base::FilePath result; |
| + if (!ExternalMountPoints::GetSystemInstance()->GetRegisteredPath(fs_name, |
| + &result)) { |
| + return base::FilePath(); |
| + } |
| + return result; |
| } |
| private: |
| // Registers and returns the file system id for the mass storage device |
| // specified by |device_id| and |path|. |
| - std::string RegisterFileSystemForMassStorage( |
| - const std::string& device_id, const base::FilePath& path) { |
| + bool RegisterFileSystemForMassStorage(const std::string& device_id, |
| + const std::string& fs_name, |
| + const base::FilePath& path) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| DCHECK(StorageInfo::IsMassStorageDevice(device_id)); |
| @@ -584,57 +681,53 @@ class MediaFileSystemRegistry::MediaFileSystemContextImpl |
| // call tree, probably by having it figure out by device id what |
| // registration is needed, or having per-device-type handlers at the |
| // next higher level. |
| - std::string fsid; |
| + bool result = false; |
| if (StorageInfo::IsITunesDevice(device_id)) { |
| - ImportedMediaGalleryRegistry* imported_registry = |
| + ImportedMediaGalleryRegistry* registry = |
| ImportedMediaGalleryRegistry::GetInstance(); |
| - fsid = imported_registry->RegisterITunesFilesystemOnUIThread(path); |
| + result = registry->RegisterITunesFilesystemOnUIThread(fs_name, path); |
| } else if (StorageInfo::IsPicasaDevice(device_id)) { |
| - ImportedMediaGalleryRegistry* imported_registry = |
| + ImportedMediaGalleryRegistry* registry = |
| ImportedMediaGalleryRegistry::GetInstance(); |
| - fsid = imported_registry->RegisterPicasaFilesystemOnUIThread( |
| - path); |
| + result = registry->RegisterPicasaFilesystemOnUIThread(fs_name, path); |
| } else if (StorageInfo::IsIPhotoDevice(device_id)) { |
| - ImportedMediaGalleryRegistry* imported_registry = |
| + ImportedMediaGalleryRegistry* registry = |
| ImportedMediaGalleryRegistry::GetInstance(); |
| - fsid = imported_registry->RegisterIPhotoFilesystemOnUIThread( |
| - path); |
| + result = registry->RegisterIPhotoFilesystemOnUIThread(fs_name, path); |
| } else { |
| - std::string fs_name(extension_misc::kMediaFileSystemPathPart); |
| - fsid = IsolatedContext::GetInstance()->RegisterFileSystemForPath( |
| - fileapi::kFileSystemTypeNativeMedia, path, &fs_name); |
| + result = ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( |
| + fs_name, fileapi::kFileSystemTypeNativeMedia, |
| + fileapi::FileSystemMountOption(), path); |
| } |
| - return fsid; |
| + return result; |
| } |
| - std::string RegisterFileSystemForMTPDevice( |
| - const std::string& device_id, const base::FilePath& path) { |
| + bool RegisterFileSystemForMTPDevice(const std::string& device_id, |
| + const std::string fs_name, |
| + const base::FilePath& path) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| DCHECK(!StorageInfo::IsMassStorageDevice(device_id)); |
| // Sanity checks for |path|. |
| CHECK(MediaStorageUtil::CanCreateFileSystem(device_id, path)); |
| - std::string fs_name(extension_misc::kMediaFileSystemPathPart); |
| - const std::string fsid = |
| - IsolatedContext::GetInstance()->RegisterFileSystemForPath( |
| - fileapi::kFileSystemTypeDeviceMedia, path, &fs_name); |
| - CHECK(!fsid.empty()); |
| + bool result = ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( |
| + fs_name, fileapi::kFileSystemTypeDeviceMedia, |
| + fileapi::FileSystemMountOption(), path); |
| + CHECK(result); |
| content::BrowserThread::PostTask( |
| content::BrowserThread::IO, FROM_HERE, base::Bind( |
| &MTPDeviceMapService::RegisterMTPFileSystem, |
| base::Unretained(MTPDeviceMapService::GetInstance()), |
| - path.value(), fsid)); |
| - return fsid; |
| + path.value(), fs_name)); |
| + return result; |
| } |
| - MediaFileSystemRegistry* registry_; |
| - |
| DISALLOW_COPY_AND_ASSIGN(MediaFileSystemContextImpl); |
| }; |
| // Constructor in 'private' section because depends on private class definition. |
| MediaFileSystemRegistry::MediaFileSystemRegistry() |
| - : file_system_context_(new MediaFileSystemContextImpl(this)) { |
| + : file_system_context_(new MediaFileSystemContextImpl) { |
| StorageMonitor::GetInstance()->AddObserver(this); |
| } |
| @@ -698,6 +791,30 @@ void MediaFileSystemRegistry::OnGalleryRemoved( |
| } |
| } |
| +ExtensionGalleriesHost* MediaFileSystemRegistry::GetExtensionGalleryHost( |
| + Profile* profile, |
| + MediaGalleriesPreferences* preferences, |
| + const std::string& extension_id) { |
| + ExtensionGalleriesHostMap::iterator extension_hosts = |
|
Lei Zhang
2014/03/20 00:46:26
Is the returned iterator guaranteed to be valid?
vandebo (ex-Chrome)
2014/03/20 18:08:53
Took awhile to figure out that it is - GetPreferen
|
| + extension_hosts_map_.find(profile); |
| + if (extension_hosts->second.empty()) |
| + preferences->AddGalleryChangeObserver(this); |
| + |
| + ExtensionGalleriesHost* result = extension_hosts->second[extension_id].get(); |
| + if (!result) { |
| + result = new ExtensionGalleriesHost( |
| + file_system_context_.get(), |
| + profile->GetPath(), |
| + extension_id, |
| + base::Bind(&MediaFileSystemRegistry::OnExtensionGalleriesHostEmpty, |
| + base::Unretained(this), |
| + profile, |
| + extension_id)); |
| + extension_hosts_map_[profile][extension_id] = result; |
| + } |
| + return result; |
| +} |
| + |
| void MediaFileSystemRegistry::OnExtensionGalleriesHostEmpty( |
| Profile* profile, const std::string& extension_id) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |