summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorvandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-07 23:38:01 +0000
committervandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-07 23:38:01 +0000
commit1a39d73e551b07893d3b7cecb3ef3ac4871d105b (patch)
tree10fb4e8a0805491d8a4b5a1a9ec98024d1e373db /chrome/browser
parentb785cd36336aac3fc41402066a28363b02bcde0d (diff)
downloadchromium_src-1a39d73e551b07893d3b7cecb3ef3ac4871d105b.zip
chromium_src-1a39d73e551b07893d3b7cecb3ef3ac4871d105b.tar.gz
chromium_src-1a39d73e551b07893d3b7cecb3ef3ac4871d105b.tar.bz2
Connect MediaFileSystemRegistry with MediaGalleriesPreferences
Refactor MediaFileSystemRegistry to make state easier to manage and connect the extension preferences to the registry. Review URL: https://chromiumcodereview.appspot.com/10871049 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@155534 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/extensions/api/media_galleries/media_galleries_api.cc6
-rw-r--r--chrome/browser/intents/device_attached_intent_source.cc4
-rw-r--r--chrome/browser/media_gallery/media_file_system_registry.cc451
-rw-r--r--chrome/browser/media_gallery/media_file_system_registry.h64
-rw-r--r--chrome/browser/system_monitor/media_storage_util.cc47
-rw-r--r--chrome/browser/system_monitor/media_storage_util.h13
6 files changed, 378 insertions, 207 deletions
diff --git a/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc b/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
index f5a40ff..e7e2927 100644
--- a/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
+++ b/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
@@ -79,7 +79,7 @@ bool MediaGalleriesGetMediaFileSystemsFunction::RunImpl() {
} else if (interactive == "if_needed") {
std::vector<MediaFileSystemRegistry::MediaFSInfo> filesystems =
MediaFileSystemRegistry::GetInstance()->GetMediaFileSystemsForExtension(
- render_view_host()->GetProcess(), *GetExtension());
+ render_view_host(), GetExtension());
if (filesystems.empty())
ShowDialog();
else
@@ -98,7 +98,7 @@ bool MediaGalleriesGetMediaFileSystemsFunction::RunImpl() {
void MediaGalleriesGetMediaFileSystemsFunction::GetAndReturnGalleries() {
std::vector<MediaFileSystemRegistry::MediaFSInfo> filesystems =
MediaFileSystemRegistry::GetInstance()->GetMediaFileSystemsForExtension(
- render_view_host()->GetProcess(), *GetExtension());
+ render_view_host(), GetExtension());
ReturnGalleries(filesystems);
}
@@ -115,7 +115,7 @@ void MediaGalleriesGetMediaFileSystemsFunction::ReturnGalleries(
"name", Value::CreateStringValue(filesystems[i].name));
list->Append(dict_value);
- if (GetExtension()->HasAPIPermission(
+ if (!filesystems[i].path.empty() && GetExtension()->HasAPIPermission(
extensions::APIPermission::kMediaGalleriesRead)) {
content::ChildProcessSecurityPolicy* policy =
ChildProcessSecurityPolicy::GetInstance();
diff --git a/chrome/browser/intents/device_attached_intent_source.cc b/chrome/browser/intents/device_attached_intent_source.cc
index 60b9666..0f0244a 100644
--- a/chrome/browser/intents/device_attached_intent_source.cc
+++ b/chrome/browser/intents/device_attached_intent_source.cc
@@ -102,9 +102,7 @@ void DeviceAttachedIntentSource::OnRemovableStorageAttached(
// Only handle mass storage for now.
// TODO(kmadhusu): Handle all device types. http://crbug.com/140353.
- MediaStorageUtil::Type type;
- MediaStorageUtil::CrackDeviceId(id, &type, NULL);
- if (type == MediaStorageUtil::MTP_OR_PTP)
+ if (!MediaStorageUtil::IsMassStorageDevice(id))
return;
DCHECK(MediaStorageUtil::IsRemovableDevice(id));
diff --git a/chrome/browser/media_gallery/media_file_system_registry.cc b/chrome/browser/media_gallery/media_file_system_registry.cc
index e2a32e1..9a39533 100644
--- a/chrome/browser/media_gallery/media_file_system_registry.cc
+++ b/chrome/browser/media_gallery/media_file_system_registry.cc
@@ -7,27 +7,35 @@
#include "chrome/browser/media_gallery/media_file_system_registry.h"
#include <set>
+#include <vector>
+#include "base/callback.h"
#include "base/file_path.h"
#include "base/path_service.h"
+#include "base/stl_util.h"
#include "base/system_monitor/system_monitor.h"
#include "base/utf_string_conversions.h"
+#include "chrome/browser/media_gallery/media_galleries_preferences.h"
+#include "chrome/browser/media_gallery/media_galleries_preferences_factory.h"
+#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/system_monitor/media_storage_util.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/extensions/extension.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
#include "webkit/fileapi/file_system_types.h"
#include "webkit/fileapi/isolated_context.h"
#include "webkit/fileapi/media/media_file_system_config.h"
#if defined(SUPPORT_MEDIA_FILESYSTEM)
#include "webkit/fileapi/media/media_device_map_service.h"
-
-using fileapi::MediaDeviceMapService;
#endif
namespace chrome {
@@ -37,23 +45,252 @@ static base::LazyInstance<MediaFileSystemRegistry>::Leaky
using base::SystemMonitor;
using content::BrowserThread;
+using content::NavigationController;
using content::RenderProcessHost;
+using content::WebContents;
using fileapi::IsolatedContext;
namespace {
-bool IsGalleryPermittedForExtension(const extensions::Extension& extension,
- const FilePath::StringType& location) {
- if (extension.HasAPIPermission(
- extensions::APIPermission::kMediaGalleriesAllGalleries)) {
- return true;
+struct InvalidatedGalleriesInfo {
+ std::set<ExtensionGalleriesHost*> extension_hosts;
+ std::set<MediaGalleryPrefId> pref_ids;
+};
+
+std::string RegisterFileSystem(std::string device_id, const FilePath& path) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ IsolatedContext* isolated_context = IsolatedContext::GetInstance();
+ if (MediaStorageUtil::IsMassStorageDevice(device_id)) {
+ // Sanity checks for |path|.
+ CHECK(path.IsAbsolute());
+ CHECK(!path.ReferencesParent());
+ std::string fs_name(extension_misc::kMediaFileSystemPathPart);
+ const std::string fsid = isolated_context->RegisterFileSystemForPath(
+ fileapi::kFileSystemTypeNativeMedia, path, &fs_name);
+ CHECK(!fsid.empty());
+ return fsid;
}
- // TODO(vandebo) Check with prefs for permission to this gallery.
- return false;
+
+ // TODO(kmadhusu) handle MTP devices.
+ NOTREACHED();
+ return std::string();
}
} // namespace
+// Refcounted only so it can easily be put in map. All instances are owned
+// by |MediaFileSystemRegistry::extension_hosts_map_|.
+class ExtensionGalleriesHost
+ : public base::RefCounted<ExtensionGalleriesHost>,
+ public content::NotificationObserver {
+ public:
+ // |no_references_callback| is called when the last RenderViewHost reference
+ // goes away. RenderViewHost references are added through ReferenceFromRVH().
+ explicit ExtensionGalleriesHost(const base::Closure& no_references_callback)
+ : no_references_callback_(no_references_callback) {
+ }
+
+ // For each gallery in the list of permitted |galleries|, looks up or creates
+ // a file system id and returns the information needed for the renderer to
+ // create those file system objects.
+ std::vector<MediaFileSystemRegistry::MediaFSInfo> GetMediaFileSystems(
+ const MediaGalleryPrefIdSet& galleries,
+ const MediaGalleriesPrefInfoMap& galleries_info) {
+ std::vector<MediaFileSystemRegistry::MediaFSInfo> result;
+ for (std::set<MediaGalleryPrefId>::const_iterator id = galleries.begin();
+ id != galleries.end();
+ ++id) {
+ PrefIdFsInfoMap::const_iterator existing_info = pref_id_map_.find(*id);
+ if (existing_info != pref_id_map_.end()) {
+ result.push_back(existing_info->second);
+ continue;
+ }
+ const MediaGalleryPrefInfo& gallery_info =
+ galleries_info.find(*id)->second;
+ const std::string& device_id = gallery_info.device_id;
+ // TODO(kmadhusu) handle MTP devices.
+ DCHECK(MediaStorageUtil::IsMassStorageDevice(device_id));
+ FilePath path = MediaStorageUtil::FindDevicePathById(device_id);
+ // TODO(vandebo) we also need to check that these galleries are attached.
+ // For now, just skip over entries that we couldn't find.
+ if (path.empty())
+ continue;
+ CHECK(!path.empty());
+ path = path.Append(gallery_info.path);
+
+ MediaFileSystemRegistry::MediaFSInfo new_entry;
+ new_entry.name = gallery_info.display_name;
+ new_entry.path = path;
+ new_entry.fsid = RegisterFileSystem(device_id, path);
+ result.push_back(new_entry);
+ pref_id_map_[*id] = new_entry;
+ }
+
+ // TODO(vandebo) We need a way of getting notification when permission for
+ // galleries are revoked (http://crbug.com/145855). For now, invalidate
+ // any fsid we have that we didn't get this time around.
+ if (galleries.size() != pref_id_map_.size()) {
+ MediaGalleryPrefIdSet old_galleries;
+ for (PrefIdFsInfoMap::const_iterator it = pref_id_map_.begin();
+ it != pref_id_map_.end();
+ ++it) {
+ old_galleries.insert(it->first);
+ }
+ MediaGalleryPrefIdSet invalid_galleries;
+ std::set_difference(old_galleries.begin(), old_galleries.end(),
+ galleries.begin(), galleries.end(),
+ std::inserter(invalid_galleries,
+ invalid_galleries.begin()));
+ for (MediaGalleryPrefIdSet::const_iterator it = invalid_galleries.begin();
+ it != invalid_galleries.end();
+ ++it) {
+ RevokeGalleryByPrefId(*it);
+ }
+ }
+
+ return result;
+ }
+
+ // TODO(kmadhusu): Clean up this code. http://crbug.com/140340.
+ // 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);
+ if (gallery == pref_id_map_.end())
+ return;
+
+ IsolatedContext* isolated_context = IsolatedContext::GetInstance();
+ isolated_context->RevokeFileSystem(gallery->second.fsid);
+
+ pref_id_map_.erase(gallery);
+ }
+
+ // Indicate that the passed |rvh| will reference the file system ids created
+ // by this class. It is safe to call this multiple times with the same RVH.
+ void ReferenceFromRVH(const content::RenderViewHost* rvh) {
+ WebContents* contents = WebContents::FromRenderViewHost(rvh);
+ if (registrar_.IsRegistered(this,
+ content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
+ content::Source<WebContents>(contents))) {
+ return;
+ }
+ registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
+ content::Source<WebContents>(contents));
+ registrar_.Add(
+ this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
+ content::Source<NavigationController>(&contents->GetController()));
+
+ RenderProcessHost* rph = contents->GetRenderProcessHost();
+ rph_refs_[rph].insert(contents);
+ if (rph_refs_[rph].size() == 1) {
+ registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
+ content::Source<RenderProcessHost>(rph));
+ }
+ }
+
+ // NotificationObserver implementation.
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE {
+ switch (type) {
+ case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
+ OnRendererProcessClosed(
+ content::Source<RenderProcessHost>(source).ptr());
+ break;
+ }
+ case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: {
+ OnWebContentsDestroyedOrNavigated(
+ content::Source<WebContents>(source).ptr());
+ break;
+ }
+ case content::NOTIFICATION_NAV_ENTRY_COMMITTED: {
+ NavigationController* controller =
+ content::Source<NavigationController>(source).ptr();
+ WebContents* contents = controller->GetWebContents();
+ OnWebContentsDestroyedOrNavigated(contents);
+ break;
+ }
+ default: {
+ NOTREACHED();
+ break;
+ }
+ }
+ }
+
+ private:
+ typedef std::map<MediaGalleryPrefId, MediaFileSystemRegistry::MediaFSInfo>
+ PrefIdFsInfoMap;
+ typedef std::map<const RenderProcessHost*, std::set<const WebContents*> >
+ RenderProcessHostRefCount;
+
+ // Private destructor and friend declaration for ref counted implementation.
+ friend class base::RefCounted<ExtensionGalleriesHost>;
+
+ virtual ~ExtensionGalleriesHost() {
+ DCHECK(rph_refs_.empty());
+ DCHECK(pref_id_map_.empty());
+ }
+
+ void OnRendererProcessClosed(const RenderProcessHost* rph) {
+ RenderProcessHostRefCount::const_iterator rph_info = rph_refs_.find(rph);
+ DCHECK(rph_info != rph_refs_.end());
+ // We're going to remove everything from the set, so we make a copy
+ // before operating on it.
+ std::set<const WebContents*> closed_web_contents = rph_info->second;
+ DCHECK(!closed_web_contents.empty());
+
+ for (std::set<const WebContents*>::const_iterator it =
+ closed_web_contents.begin();
+ it != closed_web_contents.end();
+ ++it) {
+ OnWebContentsDestroyedOrNavigated(*it);
+ }
+ }
+
+ void OnWebContentsDestroyedOrNavigated(const WebContents* contents) {
+ registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
+ content::Source<WebContents>(contents));
+ registrar_.Remove(
+ this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
+ content::Source<NavigationController>(&contents->GetController()));
+
+ RenderProcessHost* rph = contents->GetRenderProcessHost();
+ RenderProcessHostRefCount::iterator process_refs = rph_refs_.find(rph);
+ DCHECK(process_refs != rph_refs_.end());
+ process_refs->second.erase(contents);
+ if (process_refs->second.empty()) {
+ registrar_.Remove(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
+ content::Source<RenderProcessHost>(rph));
+ rph_refs_.erase(process_refs);
+ }
+
+ if (rph_refs_.empty()) {
+ IsolatedContext* isolated_context = IsolatedContext::GetInstance();
+ for (PrefIdFsInfoMap::const_iterator it = pref_id_map_.begin();
+ it != pref_id_map_.end();
+ ++it) {
+ isolated_context->RevokeFileSystem(it->second.fsid);
+ }
+ pref_id_map_.clear();
+ no_references_callback_.Run();
+ }
+ }
+
+ // A callback to call when the last RVH reference goes away.
+ base::Closure no_references_callback_;
+
+ // A map from the gallery preferences id to the file system information.
+ PrefIdFsInfoMap pref_id_map_;
+
+ // The set of render processes and web contents that may have references to
+ // the file system ids this instance manages.
+ RenderProcessHostRefCount rph_refs_;
+
+ // A registrar for listening notifications.
+ content::NotificationRegistrar registrar_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExtensionGalleriesHost);
+};
/******************
* Public methods
@@ -64,88 +301,88 @@ MediaFileSystemRegistry* MediaFileSystemRegistry::GetInstance() {
return g_media_file_system_registry.Pointer();
}
+// TODO(vandebo) We need to make this async so that we check that the
+// galleries are attached (requires the file thread).
std::vector<MediaFileSystemRegistry::MediaFSInfo>
MediaFileSystemRegistry::GetMediaFileSystemsForExtension(
- const content::RenderProcessHost* rph,
- const extensions::Extension& extension) {
+ const content::RenderViewHost* rvh,
+ const extensions::Extension* extension) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- std::vector<MediaFSInfo> results;
- std::pair<ChildIdToMediaFSMap::iterator, bool> ret =
- media_fs_map_.insert(std::make_pair(rph, MediaPathToFSIDMap()));
- ChildIdToMediaFSMap::iterator& child_it = ret.first;
- if (ret.second) {
- // Never seen a GetMediaFileSystems call from this RPH. Initialize its
- // file system mappings.
- RegisterForRPHGoneNotifications(rph);
- FilePath pictures_path;
- // TODO(vandebo) file system galleries need a unique id as well.
- if (PathService::Get(chrome::DIR_USER_PICTURES, &pictures_path) &&
- IsGalleryPermittedForExtension(extension, pictures_path.value())) {
- std::string fsid = RegisterPathAsFileSystem(pictures_path);
- child_it->second.insert(std::make_pair(pictures_path, fsid));
- }
- }
-
- // TODO(thestig) Handle overlap between devices and media directories.
- SystemMonitor* monitor = SystemMonitor::Get();
- const std::vector<SystemMonitor::RemovableStorageInfo> media_devices =
- monitor->GetAttachedRemovableStorage();
- for (size_t i = 0; i < media_devices.size(); ++i) {
- MediaStorageUtil::Type type;
- MediaStorageUtil::CrackDeviceId(media_devices[i].device_id, &type, NULL);
- // TODO(vandebo) Handle MTP devices.
- if (type != MediaStorageUtil::MTP_OR_PTP &&
- IsGalleryPermittedForExtension(extension, media_devices[i].location)) {
- device_id_map_.insert(std::make_pair(media_devices[i].device_id,
- media_devices[i]));
- FilePath path(media_devices[i].location);
- const std::string fsid = RegisterPathAsFileSystem(path);
- child_it->second.insert(std::make_pair(path, fsid));
- }
+ Profile* profile =
+ Profile::FromBrowserContext(rvh->GetProcess()->GetBrowserContext());
+ MediaGalleriesPreferences* preferences =
+ MediaGalleriesPreferencesFactory::GetForProfile(profile);
+ MediaGalleryPrefIdSet galleries =
+ preferences->GalleriesForExtension(*extension);
+ ExtensionGalleriesHost* extension_host =
+ extension_hosts_map_[profile][extension->id()].get();
+
+ // If the extension has no galleries and it didn't have any last time, just
+ // return the empty list. The second check is needed because of
+ // http://crbug.com/145855.
+ if (galleries.empty() && !extension_host)
+ return std::vector<MediaFileSystemRegistry::MediaFSInfo>();
+
+ if (!extension_host) {
+ extension_host = new ExtensionGalleriesHost(
+ base::Bind(&MediaFileSystemRegistry::OnExtensionGalleriesHostEmpty,
+ base::Unretained(this), profile, extension->id()));
+ extension_hosts_map_[profile][extension->id()] = extension_host;
}
+ extension_host->ReferenceFromRVH(rvh);
- MediaPathToFSIDMap& child_map = child_it->second;
- for (MediaPathToFSIDMap::const_iterator it = child_map.begin();
- it != child_map.end();
- ++it) {
- MediaFSInfo entry;
- // TODO(vandebo) use a better name, fsid for now.
- entry.name = it->second;
- entry.fsid = it->second;
- entry.path = it->first;
- results.push_back(entry);
- }
- return results;
+ return extension_host->GetMediaFileSystems(galleries,
+ preferences->known_galleries());
}
+// TODO(vandebo) We also need to listen for the attach event and add newly
+// attached media devices to MediaGalleriesPreferences.
void MediaFileSystemRegistry::OnRemovableStorageDetached(
const std::string& id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DeviceIdToInfoMap::iterator it = device_id_map_.find(id);
- if (it == device_id_map_.end())
- return;
+ // 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
+ // extension hosts in which they may appear (per profile) and revoked it in
+ // a second step.
+ std::vector<InvalidatedGalleriesInfo> invalid_galleries_info;
+
+ for (ExtensionGalleriesHostMap::iterator profile_it =
+ extension_hosts_map_.begin();
+ profile_it != extension_hosts_map_.end();
+ ++profile_it) {
+ MediaGalleriesPreferences* preferences =
+ MediaGalleriesPreferencesFactory::GetForProfile(profile_it->first);
+ InvalidatedGalleriesInfo invalid_galleries_in_profile;
+ invalid_galleries_in_profile.pref_ids =
+ preferences->LookUpGalleriesByDeviceId(id);
+
+ for (ExtensionHostMap::const_iterator extension_host_it =
+ profile_it->second.begin();
+ extension_host_it != profile_it->second.end();
+ ++extension_host_it) {
+ invalid_galleries_in_profile.extension_hosts.insert(
+ extension_host_it->second.get());
+ }
- FilePath path(it->second.location);
- RevokeMediaFileSystem(path);
- device_id_map_.erase(it);
-}
+ invalid_galleries_info.push_back(invalid_galleries_in_profile);
+ }
-void MediaFileSystemRegistry::Observe(
- int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- DCHECK(type == content::NOTIFICATION_RENDERER_PROCESS_CLOSED ||
- type == content::NOTIFICATION_RENDERER_PROCESS_TERMINATED);
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- const RenderProcessHost* rph =
- content::Source<content::RenderProcessHost>(source).ptr();
- ChildIdToMediaFSMap::iterator child_it = media_fs_map_.find(rph);
- CHECK(child_it != media_fs_map_.end());
- // No need to revoke the isolated file systems. The RPH will do that.
- media_fs_map_.erase(child_it);
- UnregisterForRPHGoneNotifications(rph);
+ for (size_t i = 0; i < invalid_galleries_info.size(); i++) {
+ for (std::set<ExtensionGalleriesHost*>::const_iterator extension_host_it =
+ invalid_galleries_info[i].extension_hosts.begin();
+ extension_host_it != invalid_galleries_info[i].extension_hosts.end();
+ ++extension_host_it) {
+ for (std::set<MediaGalleryPrefId>::const_iterator pref_id_it =
+ invalid_galleries_info[i].pref_ids.begin();
+ pref_id_it != invalid_galleries_info[i].pref_ids.end();
+ ++pref_id_it) {
+ (*extension_host_it)->RevokeGalleryByPrefId(*pref_id_it);
+ }
+ }
+ }
}
/******************
@@ -157,6 +394,8 @@ MediaFileSystemRegistry::MediaFileSystemRegistry() {
SystemMonitor* system_monitor = SystemMonitor::Get();
if (system_monitor)
system_monitor->AddDevicesChangedObserver(this);
+ // TODO(vandebo) We should add all the currently attached media devices
+ // to MediaGalleriesPreferences here.
}
MediaFileSystemRegistry::~MediaFileSystemRegistry() {
@@ -166,56 +405,18 @@ MediaFileSystemRegistry::~MediaFileSystemRegistry() {
system_monitor->RemoveDevicesChangedObserver(this);
}
-void MediaFileSystemRegistry::RegisterForRPHGoneNotifications(
- const content::RenderProcessHost* rph) {
- registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
- content::Source<RenderProcessHost>(rph));
- registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
- content::Source<RenderProcessHost>(rph));
-}
-
-void MediaFileSystemRegistry::UnregisterForRPHGoneNotifications(
- const content::RenderProcessHost* rph) {
- registrar_.Remove(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
- content::Source<RenderProcessHost>(rph));
- registrar_.Remove(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
- content::Source<RenderProcessHost>(rph));
-}
-
-std::string MediaFileSystemRegistry::RegisterPathAsFileSystem(
- const FilePath& path) {
+void MediaFileSystemRegistry::OnExtensionGalleriesHostEmpty(
+ Profile* profile, const std::string& extension_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- // Sanity checks for |path|.
- CHECK(path.IsAbsolute());
- CHECK(!path.ReferencesParent());
-
- // The directory name is not exposed to the js layer and we simply use
- // a fixed name (as we only register a single directory per file system).
- std::string register_name(extension_misc::kMediaFileSystemPathPart);
- const std::string fsid =
- IsolatedContext::GetInstance()->RegisterFileSystemForPath(
- fileapi::kFileSystemTypeNativeMedia, path, &register_name);
- CHECK(!fsid.empty());
- return fsid;
-}
-
-void MediaFileSystemRegistry::RevokeMediaFileSystem(const FilePath& path) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- IsolatedContext* isolated_context = IsolatedContext::GetInstance();
- isolated_context->RevokeFileSystemByPath(path);
-
- for (ChildIdToMediaFSMap::iterator child_it = media_fs_map_.begin();
- child_it != media_fs_map_.end();
- ++child_it) {
- MediaPathToFSIDMap& child_map = child_it->second;
- MediaPathToFSIDMap::iterator media_path_it = child_map.find(path);
- if (media_path_it == child_map.end())
- continue;
-
- child_map.erase(media_path_it);
- }
+ ExtensionGalleriesHostMap::iterator extension_hosts =
+ extension_hosts_map_.find(profile);
+ DCHECK(extension_hosts != extension_hosts_map_.end());
+ ExtensionHostMap::size_type erase_count =
+ extension_hosts->second.erase(extension_id);
+ DCHECK_EQ(1U, erase_count);
+ if (extension_hosts->second.empty())
+ extension_hosts_map_.erase(extension_hosts);
}
} // namespace chrome
diff --git a/chrome/browser/media_gallery/media_file_system_registry.h b/chrome/browser/media_gallery/media_file_system_registry.h
index f5267976..e6bf64a 100644
--- a/chrome/browser/media_gallery/media_file_system_registry.h
+++ b/chrome/browser/media_gallery/media_file_system_registry.h
@@ -15,14 +15,14 @@
#include "base/basictypes.h"
#include "base/lazy_instance.h"
+#include "base/file_path.h"
+#include "base/memory/ref_counted.h"
#include "base/system_monitor/system_monitor.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
-class FilePath;
+class Profile;
namespace content {
-class RenderProcessHost;
+class RenderViewHost;
}
namespace extensions {
@@ -35,12 +35,13 @@ class IsolatedContext;
namespace chrome {
+class ExtensionGalleriesHost;
+
class MediaFileSystemRegistry
- : public base::SystemMonitor::DevicesChangedObserver,
- public content::NotificationObserver {
+ : public base::SystemMonitor::DevicesChangedObserver {
public:
struct MediaFSInfo {
- std::string name;
+ string16 name;
std::string fsid;
FilePath path;
};
@@ -48,57 +49,34 @@ class MediaFileSystemRegistry
// The instance is lazily created per browser process.
static MediaFileSystemRegistry* GetInstance();
- // Returns the list of media filesystem IDs and paths for a given RPH.
+ // Returns the list of media filesystem IDs and paths for a given RVH.
// Called on the UI thread.
std::vector<MediaFSInfo> GetMediaFileSystemsForExtension(
- const content::RenderProcessHost* rph,
- const extensions::Extension& extension);
+ const content::RenderViewHost* rvh,
+ const extensions::Extension* extension);
// base::SystemMonitor::DevicesChangedObserver implementation.
virtual void OnRemovableStorageDetached(const std::string& id) OVERRIDE;
- // content::NotificationObserver implementation.
- virtual void Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) OVERRIDE;
-
private:
friend struct base::DefaultLazyInstanceTraits<MediaFileSystemRegistry>;
- // Mapping of media directories to filesystem IDs.
- typedef std::map<FilePath, std::string> MediaPathToFSIDMap;
-
- // Mapping of RPH to MediaPathToFSIDMaps.
- typedef std::map<const content::RenderProcessHost*,
- MediaPathToFSIDMap> ChildIdToMediaFSMap;
-
- // Mapping of device id to media device info.
- typedef std::map<std::string, base::SystemMonitor::RemovableStorageInfo>
- DeviceIdToInfoMap;
+ // Map an extension to the ExtensionGalleriesHost.
+ typedef std::map<std::string /*extension_id*/,
+ scoped_refptr<ExtensionGalleriesHost> > ExtensionHostMap;
+ // Map a profile and extension to the ExtensionGalleriesHost.
+ typedef std::map<Profile*, ExtensionHostMap> ExtensionGalleriesHostMap;
// Obtain an instance of this class via GetInstance().
MediaFileSystemRegistry();
virtual ~MediaFileSystemRegistry();
- // Helper functions to register / unregister listening for renderer process
- // closed / terminiated notifications.
- void RegisterForRPHGoneNotifications(const content::RenderProcessHost* rph);
- void UnregisterForRPHGoneNotifications(const content::RenderProcessHost* rph);
-
- // Registers a path as a media file system and return the filesystem id.
- std::string RegisterPathAsFileSystem(const FilePath& path);
-
- // Revoke a media file system with a given |path|.
- void RevokeMediaFileSystem(const FilePath& path);
-
- // Only accessed on the UI thread.
- ChildIdToMediaFSMap media_fs_map_;
-
- // Only accessed on the UI thread.
- DeviceIdToInfoMap device_id_map_;
+ void OnExtensionGalleriesHostEmpty(Profile* profile,
+ const std::string& extension_id);
- // Is only used on the UI thread.
- content::NotificationRegistrar registrar_;
+ // Only accessed on the UI thread. This map owns all the
+ // ExtensionGalleriesHost objects created.
+ ExtensionGalleriesHostMap extension_hosts_map_;
DISALLOW_COPY_AND_ASSIGN(MediaFileSystemRegistry);
};
diff --git a/chrome/browser/system_monitor/media_storage_util.cc b/chrome/browser/system_monitor/media_storage_util.cc
index a5dce62..8a0d057 100644
--- a/chrome/browser/system_monitor/media_storage_util.cc
+++ b/chrome/browser/system_monitor/media_storage_util.cc
@@ -33,19 +33,11 @@ static void (*g_test_get_device_info_from_path_function)(
const FilePath& path, std::string* device_id, string16* device_name,
FilePath* relative_path) = NULL;
-void EmptyPathIsFalseCallback(const MediaStorageUtil::BoolCallback& callback,
- FilePath path) {
- callback.Run(!path.empty());
-}
-
void ValidatePathOnFileThread(
- const FilePath& path, const MediaStorageUtil::FilePathCallback& callback) {
+ const FilePath& path, const MediaStorageUtil::BoolCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- FilePath result;
- if (file_util::PathExists(path))
- result = path;
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(callback, path));
+ base::Bind(callback, file_util::PathExists(path)));
}
FilePath::StringType FindRemovableStorageLocationById(
@@ -123,6 +115,12 @@ bool MediaStorageUtil::IsRemovableDevice(const std::string& device_id) {
}
// static
+bool MediaStorageUtil::IsMassStorageDevice(const std::string& device_id) {
+ Type type;
+ return CrackDeviceId(device_id, &type, NULL) && type != MTP_OR_PTP;
+}
+
+// static
void MediaStorageUtil::IsDeviceAttached(const std::string& device_id,
const BoolCallback& callback) {
Type type;
@@ -141,11 +139,10 @@ void MediaStorageUtil::IsDeviceAttached(const std::string& device_id,
break;
case FIXED_MASS_STORAGE:
// For this type, the unique_id is the path.
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&ValidatePathOnFileThread,
- FilePath::FromUTF8Unsafe(unique_id),
- base::Bind(&EmptyPathIsFalseCallback, callback)));
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(&ValidatePathOnFileThread,
+ FilePath::FromUTF8Unsafe(unique_id),
+ callback));
break;
}
NOTREACHED();
@@ -166,32 +163,26 @@ void MediaStorageUtil::GetDeviceInfoFromPath(const FilePath& path,
}
// static
-void MediaStorageUtil::FindDevicePathById(const std::string& device_id,
- const FilePathCallback& callback) {
+FilePath MediaStorageUtil::FindDevicePathById(const std::string& device_id) {
Type type;
std::string unique_id;
if (!CrackDeviceId(device_id, &type, &unique_id))
- callback.Run(FilePath());
+ return FilePath();
switch (type) {
case MTP_OR_PTP:
// TODO(kmadhusu) We may want to return the MTP device location here.
- callback.Run(FilePath());
- break;
+ return FilePath();
case REMOVABLE_MASS_STORAGE_WITH_DCIM: // Fall through.
case REMOVABLE_MASS_STORAGE_NO_DCIM:
- callback.Run(FilePath(FindRemovableStorageLocationById(device_id)));
- break;
+ return FilePath(FindRemovableStorageLocationById(device_id));
case FIXED_MASS_STORAGE:
// For this type, the unique_id is the path.
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&ValidatePathOnFileThread,
- FilePath::FromUTF8Unsafe(unique_id), callback));
- break;
+ return FilePath::FromUTF8Unsafe(unique_id);
}
+
NOTREACHED();
- callback.Run(FilePath());
+ return FilePath();
}
// static
diff --git a/chrome/browser/system_monitor/media_storage_util.h b/chrome/browser/system_monitor/media_storage_util.h
index 827b8ce..bccaec5 100644
--- a/chrome/browser/system_monitor/media_storage_util.h
+++ b/chrome/browser/system_monitor/media_storage_util.h
@@ -30,7 +30,6 @@ class MediaStorageUtil {
};
typedef base::Callback<void(bool)> BoolCallback;
- typedef base::Callback<void(FilePath)> FilePathCallback;
// Returns a device id given properties of the device. A prefix dependent on
// |type| is added so |unique_id| need only be unique within the given type.
@@ -50,6 +49,10 @@ class MediaStorageUtil {
// (type isn't FIXED_MASS_STORAGE).
static bool IsRemovableDevice(const std::string& device_id);
+ // Looks inside |device_id| to determine if it is a mass storage device
+ // (type isn't MTP_OR_PTP).
+ static bool IsMassStorageDevice(const std::string& device_id);
+
// Determines if the device is attached to the computer.
static void IsDeviceAttached(const std::string& device_id,
const BoolCallback& callback);
@@ -61,10 +64,10 @@ class MediaStorageUtil {
string16* device_name,
FilePath* relative_path);
- // Get a FilePath for the given |device_id|. If the device isn't connected
- // or isn't a mass storage type, the FilePath will be empty.
- static void FindDevicePathById(const std::string& device_id,
- const FilePathCallback& callback);
+ // Get a FilePath for the given |device_id|. If the device isn't a mass
+ // storage type, the FilePath will be empty. This does not check that
+ // the device is connected.
+ static FilePath FindDevicePathById(const std::string& device_id);
protected:
typedef void (*GetDeviceInfoFromPathFunction)(const FilePath& path,