| 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 | 11 |
| 12 #include "base/callback.h" |
| 11 #include "base/file_path.h" | 13 #include "base/file_path.h" |
| 12 #include "base/path_service.h" | 14 #include "base/path_service.h" |
| 15 #include "base/stl_util.h" |
| 13 #include "base/system_monitor/system_monitor.h" | 16 #include "base/system_monitor/system_monitor.h" |
| 14 #include "base/utf_string_conversions.h" | 17 #include "base/utf_string_conversions.h" |
| 18 #include "chrome/browser/media_gallery/media_galleries_preferences.h" |
| 19 #include "chrome/browser/media_gallery/media_galleries_preferences_factory.h" |
| 20 #include "chrome/browser/profiles/profile.h" |
| 15 #include "chrome/browser/system_monitor/media_storage_util.h" | 21 #include "chrome/browser/system_monitor/media_storage_util.h" |
| 16 #include "chrome/common/chrome_paths.h" | 22 #include "chrome/common/chrome_paths.h" |
| 17 #include "chrome/common/extensions/extension_constants.h" | 23 #include "chrome/common/extensions/extension_constants.h" |
| 18 #include "chrome/common/extensions/extension.h" | 24 #include "chrome/common/extensions/extension.h" |
| 19 #include "content/public/browser/browser_thread.h" | 25 #include "content/public/browser/browser_thread.h" |
| 26 #include "content/public/browser/notification_observer.h" |
| 27 #include "content/public/browser/notification_registrar.h" |
| 20 #include "content/public/browser/notification_source.h" | 28 #include "content/public/browser/notification_source.h" |
| 21 #include "content/public/browser/notification_types.h" | 29 #include "content/public/browser/notification_types.h" |
| 22 #include "content/public/browser/render_process_host.h" | 30 #include "content/public/browser/render_process_host.h" |
| 31 #include "content/public/browser/render_view_host.h" |
| 32 #include "content/public/browser/web_contents.h" |
| 23 #include "webkit/fileapi/file_system_types.h" | 33 #include "webkit/fileapi/file_system_types.h" |
| 24 #include "webkit/fileapi/isolated_context.h" | 34 #include "webkit/fileapi/isolated_context.h" |
| 25 #include "webkit/fileapi/media/media_file_system_config.h" | 35 #include "webkit/fileapi/media/media_file_system_config.h" |
| 26 | 36 |
| 27 #if defined(SUPPORT_MEDIA_FILESYSTEM) | 37 #if defined(SUPPORT_MEDIA_FILESYSTEM) |
| 28 #include "webkit/fileapi/media/media_device_map_service.h" | 38 #include "webkit/fileapi/media/media_device_map_service.h" |
| 29 | |
| 30 using fileapi::MediaDeviceMapService; | |
| 31 #endif | 39 #endif |
| 32 | 40 |
| 33 namespace chrome { | 41 namespace chrome { |
| 34 | 42 |
| 35 static base::LazyInstance<MediaFileSystemRegistry>::Leaky | 43 static base::LazyInstance<MediaFileSystemRegistry>::Leaky |
| 36 g_media_file_system_registry = LAZY_INSTANCE_INITIALIZER; | 44 g_media_file_system_registry = LAZY_INSTANCE_INITIALIZER; |
| 37 | 45 |
| 38 using base::SystemMonitor; | 46 using base::SystemMonitor; |
| 39 using content::BrowserThread; | 47 using content::BrowserThread; |
| 48 using content::NavigationController; |
| 40 using content::RenderProcessHost; | 49 using content::RenderProcessHost; |
| 50 using content::WebContents; |
| 41 using fileapi::IsolatedContext; | 51 using fileapi::IsolatedContext; |
| 42 | 52 |
| 43 namespace { | 53 namespace { |
| 44 | 54 |
| 45 bool IsGalleryPermittedForExtension(const extensions::Extension& extension, | 55 struct InvalidatedGalleriesInfo { |
| 46 const FilePath::StringType& location) { | 56 std::set<ExtensionGalleriesHost*> extension_hosts; |
| 47 if (extension.HasAPIPermission( | 57 std::set<MediaGalleryPrefId> pref_ids; |
| 48 extensions::APIPermission::kMediaGalleriesAllGalleries)) { | 58 }; |
| 49 return true; | 59 |
| 50 } | 60 std::string RegisterFileSystem(std::string device_id, const FilePath& path) { |
| 51 // TODO(vandebo) Check with prefs for permission to this gallery. | 61 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 52 return false; | 62 |
| 63 IsolatedContext* isolated_context = IsolatedContext::GetInstance(); |
| 64 if (MediaStorageUtil::IsMassStorageDevice(device_id)) { |
| 65 // Sanity checks for |path|. |
| 66 CHECK(path.IsAbsolute()); |
| 67 CHECK(!path.ReferencesParent()); |
| 68 std::string fs_name(extension_misc::kMediaFileSystemPathPart); |
| 69 const std::string fsid = isolated_context->RegisterFileSystemForPath( |
| 70 fileapi::kFileSystemTypeNativeMedia, path, &fs_name); |
| 71 CHECK(!fsid.empty()); |
| 72 return fsid; |
| 73 } |
| 74 |
| 75 // TODO(kmadhusu) handle MTP devices. |
| 76 NOTREACHED(); |
| 77 return std::string(); |
| 53 } | 78 } |
| 54 | 79 |
| 55 } // namespace | 80 } // namespace |
| 56 | 81 |
| 82 // Refcounted only so it can easily be put in map. All instances are owned |
| 83 // by |MediaFileSystemRegistry::extension_hosts_map_|. |
| 84 class ExtensionGalleriesHost |
| 85 : public base::RefCounted<ExtensionGalleriesHost>, |
| 86 public content::NotificationObserver { |
| 87 public: |
| 88 // |no_references_callback| is called when the last RenderViewHost reference |
| 89 // goes away. RenderViewHost references are added through ReferenceFromRVH(). |
| 90 explicit ExtensionGalleriesHost(const base::Closure& no_references_callback) |
| 91 : no_references_callback_(no_references_callback) { |
| 92 } |
| 93 |
| 94 // For each gallery in the list of permitted |galleries|, looks up or creates |
| 95 // a file system id and returns the information needed for the renderer to |
| 96 // create those file system objects. |
| 97 std::vector<MediaFileSystemRegistry::MediaFSInfo> GetMediaFileSystems( |
| 98 const MediaGalleryPrefIdSet& galleries, |
| 99 const MediaGalleriesPrefInfoMap& galleries_info) { |
| 100 std::vector<MediaFileSystemRegistry::MediaFSInfo> result; |
| 101 for (std::set<MediaGalleryPrefId>::const_iterator id = galleries.begin(); |
| 102 id != galleries.end(); |
| 103 ++id) { |
| 104 PrefIdFsInfoMap::const_iterator existing_info = pref_id_map_.find(*id); |
| 105 if (existing_info != pref_id_map_.end()) { |
| 106 result.push_back(existing_info->second); |
| 107 continue; |
| 108 } |
| 109 const MediaGalleryPrefInfo& gallery_info = |
| 110 galleries_info.find(*id)->second; |
| 111 const std::string& device_id = gallery_info.device_id; |
| 112 // TODO(kmadhusu) handle MTP devices. |
| 113 DCHECK(MediaStorageUtil::IsMassStorageDevice(device_id)); |
| 114 FilePath path = MediaStorageUtil::FindDevicePathById(device_id); |
| 115 // TODO(vandebo) we also need to check that these galleries are attached. |
| 116 // For now, just skip over entries that we couldn't find. |
| 117 if (path.empty()) |
| 118 continue; |
| 119 CHECK(!path.empty()); |
| 120 path = path.Append(gallery_info.path); |
| 121 |
| 122 MediaFileSystemRegistry::MediaFSInfo new_entry; |
| 123 new_entry.name = gallery_info.display_name; |
| 124 new_entry.path = path; |
| 125 new_entry.fsid = RegisterFileSystem(device_id, path); |
| 126 result.push_back(new_entry); |
| 127 pref_id_map_[*id] = new_entry; |
| 128 } |
| 129 |
| 130 // TODO(vandebo) We need a way of getting notification when permission for |
| 131 // galleries are revoked (http://crbug.com/145855). For now, invalidate |
| 132 // any fsid we have that we didn't get this time around. |
| 133 if (galleries.size() != pref_id_map_.size()) { |
| 134 MediaGalleryPrefIdSet old_galleries; |
| 135 for (PrefIdFsInfoMap::const_iterator it = pref_id_map_.begin(); |
| 136 it != pref_id_map_.end(); |
| 137 ++it) { |
| 138 old_galleries.insert(it->first); |
| 139 } |
| 140 MediaGalleryPrefIdSet invalid_galleries; |
| 141 std::set_difference(old_galleries.begin(), old_galleries.end(), |
| 142 galleries.begin(), galleries.end(), |
| 143 std::inserter(invalid_galleries, |
| 144 invalid_galleries.begin())); |
| 145 for (MediaGalleryPrefIdSet::const_iterator it = invalid_galleries.begin(); |
| 146 it != invalid_galleries.end(); |
| 147 ++it) { |
| 148 RevokeGalleryByPrefId(*it); |
| 149 } |
| 150 } |
| 151 |
| 152 return result; |
| 153 } |
| 154 |
| 155 // TODO(kmadhusu): Clean up this code. http://crbug.com/140340. |
| 156 // Revoke the file system for |id| if this extension has created one for |id|. |
| 157 void RevokeGalleryByPrefId(MediaGalleryPrefId id) { |
| 158 PrefIdFsInfoMap::iterator gallery = pref_id_map_.find(id); |
| 159 if (gallery == pref_id_map_.end()) |
| 160 return; |
| 161 |
| 162 IsolatedContext* isolated_context = IsolatedContext::GetInstance(); |
| 163 isolated_context->RevokeFileSystem(gallery->second.fsid); |
| 164 |
| 165 pref_id_map_.erase(gallery); |
| 166 } |
| 167 |
| 168 // Indicate that the passed |rvh| will reference the file system ids created |
| 169 // by this class. It is safe to call this multiple times with the same RVH. |
| 170 void ReferenceFromRVH(const content::RenderViewHost* rvh) { |
| 171 WebContents* contents = WebContents::FromRenderViewHost(rvh); |
| 172 if (registrar_.IsRegistered(this, |
| 173 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| 174 content::Source<WebContents>(contents))) { |
| 175 return; |
| 176 } |
| 177 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| 178 content::Source<WebContents>(contents)); |
| 179 registrar_.Add( |
| 180 this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| 181 content::Source<NavigationController>(&contents->GetController())); |
| 182 |
| 183 RenderProcessHost* rph = contents->GetRenderProcessHost(); |
| 184 rph_refs_[rph].insert(contents); |
| 185 if (rph_refs_[rph].size() == 1) { |
| 186 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, |
| 187 content::Source<RenderProcessHost>(rph)); |
| 188 } |
| 189 } |
| 190 |
| 191 // NotificationObserver implementation. |
| 192 virtual void Observe(int type, |
| 193 const content::NotificationSource& source, |
| 194 const content::NotificationDetails& details) OVERRIDE { |
| 195 switch (type) { |
| 196 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { |
| 197 OnRendererProcessClosed( |
| 198 content::Source<RenderProcessHost>(source).ptr()); |
| 199 break; |
| 200 } |
| 201 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { |
| 202 OnWebContentsDestroyedOrNavigated( |
| 203 content::Source<WebContents>(source).ptr()); |
| 204 break; |
| 205 } |
| 206 case content::NOTIFICATION_NAV_ENTRY_COMMITTED: { |
| 207 NavigationController* controller = |
| 208 content::Source<NavigationController>(source).ptr(); |
| 209 WebContents* contents = controller->GetWebContents(); |
| 210 OnWebContentsDestroyedOrNavigated(contents); |
| 211 break; |
| 212 } |
| 213 default: { |
| 214 NOTREACHED(); |
| 215 break; |
| 216 } |
| 217 } |
| 218 } |
| 219 |
| 220 private: |
| 221 typedef std::map<MediaGalleryPrefId, MediaFileSystemRegistry::MediaFSInfo> |
| 222 PrefIdFsInfoMap; |
| 223 typedef std::map<const RenderProcessHost*, std::set<const WebContents*> > |
| 224 RenderProcessHostRefCount; |
| 225 |
| 226 // Private destructor and friend declaration for ref counted implementation. |
| 227 friend class base::RefCounted<ExtensionGalleriesHost>; |
| 228 |
| 229 virtual ~ExtensionGalleriesHost() { |
| 230 DCHECK(rph_refs_.empty()); |
| 231 DCHECK(pref_id_map_.empty()); |
| 232 } |
| 233 |
| 234 void OnRendererProcessClosed(const RenderProcessHost* rph) { |
| 235 RenderProcessHostRefCount::const_iterator rph_info = rph_refs_.find(rph); |
| 236 DCHECK(rph_info != rph_refs_.end()); |
| 237 // We're going to remove everything from the set, so we make a copy |
| 238 // before operating on it. |
| 239 std::set<const WebContents*> closed_web_contents = rph_info->second; |
| 240 DCHECK(!closed_web_contents.empty()); |
| 241 |
| 242 for (std::set<const WebContents*>::const_iterator it = |
| 243 closed_web_contents.begin(); |
| 244 it != closed_web_contents.end(); |
| 245 ++it) { |
| 246 OnWebContentsDestroyedOrNavigated(*it); |
| 247 } |
| 248 } |
| 249 |
| 250 void OnWebContentsDestroyedOrNavigated(const WebContents* contents) { |
| 251 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| 252 content::Source<WebContents>(contents)); |
| 253 registrar_.Remove( |
| 254 this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| 255 content::Source<NavigationController>(&contents->GetController())); |
| 256 |
| 257 RenderProcessHost* rph = contents->GetRenderProcessHost(); |
| 258 RenderProcessHostRefCount::iterator process_refs = rph_refs_.find(rph); |
| 259 DCHECK(process_refs != rph_refs_.end()); |
| 260 process_refs->second.erase(contents); |
| 261 if (process_refs->second.empty()) { |
| 262 registrar_.Remove(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, |
| 263 content::Source<RenderProcessHost>(rph)); |
| 264 rph_refs_.erase(process_refs); |
| 265 } |
| 266 |
| 267 if (rph_refs_.empty()) { |
| 268 IsolatedContext* isolated_context = IsolatedContext::GetInstance(); |
| 269 for (PrefIdFsInfoMap::const_iterator it = pref_id_map_.begin(); |
| 270 it != pref_id_map_.end(); |
| 271 ++it) { |
| 272 isolated_context->RevokeFileSystem(it->second.fsid); |
| 273 } |
| 274 pref_id_map_.clear(); |
| 275 no_references_callback_.Run(); |
| 276 } |
| 277 } |
| 278 |
| 279 // A callback to call when the last RVH reference goes away. |
| 280 base::Closure no_references_callback_; |
| 281 |
| 282 // A map from the gallery preferences id to the file system information. |
| 283 PrefIdFsInfoMap pref_id_map_; |
| 284 |
| 285 // The set of render processes and web contents that may have references to |
| 286 // the file system ids this instance manages. |
| 287 RenderProcessHostRefCount rph_refs_; |
| 288 |
| 289 // A registrar for listening notifications. |
| 290 content::NotificationRegistrar registrar_; |
| 291 |
| 292 DISALLOW_COPY_AND_ASSIGN(ExtensionGalleriesHost); |
| 293 }; |
| 57 | 294 |
| 58 /****************** | 295 /****************** |
| 59 * Public methods | 296 * Public methods |
| 60 ******************/ | 297 ******************/ |
| 61 | 298 |
| 62 // static | 299 // static |
| 63 MediaFileSystemRegistry* MediaFileSystemRegistry::GetInstance() { | 300 MediaFileSystemRegistry* MediaFileSystemRegistry::GetInstance() { |
| 64 return g_media_file_system_registry.Pointer(); | 301 return g_media_file_system_registry.Pointer(); |
| 65 } | 302 } |
| 66 | 303 |
| 304 // TODO(vandebo) We need to make this async so that we check that the |
| 305 // galleries are attached (requires the file thread). |
| 67 std::vector<MediaFileSystemRegistry::MediaFSInfo> | 306 std::vector<MediaFileSystemRegistry::MediaFSInfo> |
| 68 MediaFileSystemRegistry::GetMediaFileSystemsForExtension( | 307 MediaFileSystemRegistry::GetMediaFileSystemsForExtension( |
| 69 const content::RenderProcessHost* rph, | 308 const content::RenderViewHost* rvh, |
| 70 const extensions::Extension& extension) { | 309 const extensions::Extension* extension) { |
| 71 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 310 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 72 | 311 |
| 73 std::vector<MediaFSInfo> results; | 312 Profile* profile = |
| 74 std::pair<ChildIdToMediaFSMap::iterator, bool> ret = | 313 Profile::FromBrowserContext(rvh->GetProcess()->GetBrowserContext()); |
| 75 media_fs_map_.insert(std::make_pair(rph, MediaPathToFSIDMap())); | 314 MediaGalleriesPreferences* preferences = |
| 76 ChildIdToMediaFSMap::iterator& child_it = ret.first; | 315 MediaGalleriesPreferencesFactory::GetForProfile(profile); |
| 77 if (ret.second) { | 316 MediaGalleryPrefIdSet galleries = |
| 78 // Never seen a GetMediaFileSystems call from this RPH. Initialize its | 317 preferences->GalleriesForExtension(*extension); |
| 79 // file system mappings. | 318 ExtensionGalleriesHost* extension_host = |
| 80 RegisterForRPHGoneNotifications(rph); | 319 extension_hosts_map_[profile][extension->id()].get(); |
| 81 FilePath pictures_path; | 320 |
| 82 // TODO(vandebo) file system galleries need a unique id as well. | 321 // If the extension has no galleries and it didn't have any last time, just |
| 83 if (PathService::Get(chrome::DIR_USER_PICTURES, &pictures_path) && | 322 // return the empty list. The second check is needed because of |
| 84 IsGalleryPermittedForExtension(extension, pictures_path.value())) { | 323 // http://crbug.com/145855. |
| 85 std::string fsid = RegisterPathAsFileSystem(pictures_path); | 324 if (galleries.empty() && !extension_host) |
| 86 child_it->second.insert(std::make_pair(pictures_path, fsid)); | 325 return std::vector<MediaFileSystemRegistry::MediaFSInfo>(); |
| 87 } | 326 |
| 327 if (!extension_host) { |
| 328 extension_host = new ExtensionGalleriesHost( |
| 329 base::Bind(&MediaFileSystemRegistry::OnExtensionGalleriesHostEmpty, |
| 330 base::Unretained(this), profile, extension->id())); |
| 331 extension_hosts_map_[profile][extension->id()] = extension_host; |
| 88 } | 332 } |
| 333 extension_host->ReferenceFromRVH(rvh); |
| 89 | 334 |
| 90 // TODO(thestig) Handle overlap between devices and media directories. | 335 return extension_host->GetMediaFileSystems(galleries, |
| 91 SystemMonitor* monitor = SystemMonitor::Get(); | 336 preferences->known_galleries()); |
| 92 const std::vector<SystemMonitor::RemovableStorageInfo> media_devices = | |
| 93 monitor->GetAttachedRemovableStorage(); | |
| 94 for (size_t i = 0; i < media_devices.size(); ++i) { | |
| 95 MediaStorageUtil::Type type; | |
| 96 MediaStorageUtil::CrackDeviceId(media_devices[i].device_id, &type, NULL); | |
| 97 // TODO(vandebo) Handle MTP devices. | |
| 98 if (type != MediaStorageUtil::MTP_OR_PTP && | |
| 99 IsGalleryPermittedForExtension(extension, media_devices[i].location)) { | |
| 100 device_id_map_.insert(std::make_pair(media_devices[i].device_id, | |
| 101 media_devices[i])); | |
| 102 FilePath path(media_devices[i].location); | |
| 103 const std::string fsid = RegisterPathAsFileSystem(path); | |
| 104 child_it->second.insert(std::make_pair(path, fsid)); | |
| 105 } | |
| 106 } | |
| 107 | |
| 108 MediaPathToFSIDMap& child_map = child_it->second; | |
| 109 for (MediaPathToFSIDMap::const_iterator it = child_map.begin(); | |
| 110 it != child_map.end(); | |
| 111 ++it) { | |
| 112 MediaFSInfo entry; | |
| 113 // TODO(vandebo) use a better name, fsid for now. | |
| 114 entry.name = it->second; | |
| 115 entry.fsid = it->second; | |
| 116 entry.path = it->first; | |
| 117 results.push_back(entry); | |
| 118 } | |
| 119 return results; | |
| 120 } | 337 } |
| 121 | 338 |
| 339 // TODO(vandebo) We also need to listen for the attach event and add newly |
| 340 // attached media devices to MediaGalleriesPreferences. |
| 122 void MediaFileSystemRegistry::OnRemovableStorageDetached( | 341 void MediaFileSystemRegistry::OnRemovableStorageDetached( |
| 123 const std::string& id) { | 342 const std::string& id) { |
| 124 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 343 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 125 | 344 |
| 126 DeviceIdToInfoMap::iterator it = device_id_map_.find(id); | 345 // Since revoking a gallery in the ExtensionGalleriesHost may cause it |
| 127 if (it == device_id_map_.end()) | 346 // to be removed from the map and therefore invalidate any iterator pointing |
| 128 return; | 347 // to it, this code first copies all the invalid gallery ids and the |
| 348 // extension hosts in which they may appear (per profile) and revoked it in |
| 349 // a second step. |
| 350 std::vector<InvalidatedGalleriesInfo> invalid_galleries_info; |
| 129 | 351 |
| 130 FilePath path(it->second.location); | 352 for (ExtensionGalleriesHostMap::iterator profile_it = |
| 131 RevokeMediaFileSystem(path); | 353 extension_hosts_map_.begin(); |
| 132 device_id_map_.erase(it); | 354 profile_it != extension_hosts_map_.end(); |
| 133 } | 355 ++profile_it) { |
| 356 MediaGalleriesPreferences* preferences = |
| 357 MediaGalleriesPreferencesFactory::GetForProfile(profile_it->first); |
| 358 InvalidatedGalleriesInfo invalid_galleries_in_profile; |
| 359 invalid_galleries_in_profile.pref_ids = |
| 360 preferences->LookUpGalleriesByDeviceId(id); |
| 134 | 361 |
| 135 void MediaFileSystemRegistry::Observe( | 362 for (ExtensionHostMap::const_iterator extension_host_it = |
| 136 int type, | 363 profile_it->second.begin(); |
| 137 const content::NotificationSource& source, | 364 extension_host_it != profile_it->second.end(); |
| 138 const content::NotificationDetails& details) { | 365 ++extension_host_it) { |
| 139 DCHECK(type == content::NOTIFICATION_RENDERER_PROCESS_CLOSED || | 366 invalid_galleries_in_profile.extension_hosts.insert( |
| 140 type == content::NOTIFICATION_RENDERER_PROCESS_TERMINATED); | 367 extension_host_it->second.get()); |
| 141 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 368 } |
| 142 const RenderProcessHost* rph = | 369 |
| 143 content::Source<content::RenderProcessHost>(source).ptr(); | 370 invalid_galleries_info.push_back(invalid_galleries_in_profile); |
| 144 ChildIdToMediaFSMap::iterator child_it = media_fs_map_.find(rph); | 371 } |
| 145 CHECK(child_it != media_fs_map_.end()); | 372 |
| 146 // No need to revoke the isolated file systems. The RPH will do that. | 373 for (size_t i = 0; i < invalid_galleries_info.size(); i++) { |
| 147 media_fs_map_.erase(child_it); | 374 for (std::set<ExtensionGalleriesHost*>::const_iterator extension_host_it = |
| 148 UnregisterForRPHGoneNotifications(rph); | 375 invalid_galleries_info[i].extension_hosts.begin(); |
| 376 extension_host_it != invalid_galleries_info[i].extension_hosts.end(); |
| 377 ++extension_host_it) { |
| 378 for (std::set<MediaGalleryPrefId>::const_iterator pref_id_it = |
| 379 invalid_galleries_info[i].pref_ids.begin(); |
| 380 pref_id_it != invalid_galleries_info[i].pref_ids.end(); |
| 381 ++pref_id_it) { |
| 382 (*extension_host_it)->RevokeGalleryByPrefId(*pref_id_it); |
| 383 } |
| 384 } |
| 385 } |
| 149 } | 386 } |
| 150 | 387 |
| 151 /****************** | 388 /****************** |
| 152 * Private methods | 389 * Private methods |
| 153 ******************/ | 390 ******************/ |
| 154 | 391 |
| 155 MediaFileSystemRegistry::MediaFileSystemRegistry() { | 392 MediaFileSystemRegistry::MediaFileSystemRegistry() { |
| 156 // SystemMonitor may be NULL in unit tests. | 393 // SystemMonitor may be NULL in unit tests. |
| 157 SystemMonitor* system_monitor = SystemMonitor::Get(); | 394 SystemMonitor* system_monitor = SystemMonitor::Get(); |
| 158 if (system_monitor) | 395 if (system_monitor) |
| 159 system_monitor->AddDevicesChangedObserver(this); | 396 system_monitor->AddDevicesChangedObserver(this); |
| 397 // TODO(vandebo) We should add all the currently attached media devices |
| 398 // to MediaGalleriesPreferences here. |
| 160 } | 399 } |
| 161 | 400 |
| 162 MediaFileSystemRegistry::~MediaFileSystemRegistry() { | 401 MediaFileSystemRegistry::~MediaFileSystemRegistry() { |
| 163 // SystemMonitor may be NULL in unit tests. | 402 // SystemMonitor may be NULL in unit tests. |
| 164 SystemMonitor* system_monitor = SystemMonitor::Get(); | 403 SystemMonitor* system_monitor = SystemMonitor::Get(); |
| 165 if (system_monitor) | 404 if (system_monitor) |
| 166 system_monitor->RemoveDevicesChangedObserver(this); | 405 system_monitor->RemoveDevicesChangedObserver(this); |
| 167 } | 406 } |
| 168 | 407 |
| 169 void MediaFileSystemRegistry::RegisterForRPHGoneNotifications( | 408 void MediaFileSystemRegistry::OnExtensionGalleriesHostEmpty( |
| 170 const content::RenderProcessHost* rph) { | 409 Profile* profile, const std::string& extension_id) { |
| 171 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | |
| 172 content::Source<RenderProcessHost>(rph)); | |
| 173 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | |
| 174 content::Source<RenderProcessHost>(rph)); | |
| 175 } | |
| 176 | |
| 177 void MediaFileSystemRegistry::UnregisterForRPHGoneNotifications( | |
| 178 const content::RenderProcessHost* rph) { | |
| 179 registrar_.Remove(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | |
| 180 content::Source<RenderProcessHost>(rph)); | |
| 181 registrar_.Remove(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | |
| 182 content::Source<RenderProcessHost>(rph)); | |
| 183 } | |
| 184 | |
| 185 std::string MediaFileSystemRegistry::RegisterPathAsFileSystem( | |
| 186 const FilePath& path) { | |
| 187 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 410 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 188 | 411 |
| 189 // Sanity checks for |path|. | 412 ExtensionGalleriesHostMap::iterator extension_hosts = |
| 190 CHECK(path.IsAbsolute()); | 413 extension_hosts_map_.find(profile); |
| 191 CHECK(!path.ReferencesParent()); | 414 DCHECK(extension_hosts != extension_hosts_map_.end()); |
| 192 | 415 ExtensionHostMap::size_type erase_count = |
| 193 // The directory name is not exposed to the js layer and we simply use | 416 extension_hosts->second.erase(extension_id); |
| 194 // a fixed name (as we only register a single directory per file system). | 417 DCHECK_EQ(1U, erase_count); |
| 195 std::string register_name(extension_misc::kMediaFileSystemPathPart); | 418 if (extension_hosts->second.empty()) |
| 196 const std::string fsid = | 419 extension_hosts_map_.erase(extension_hosts); |
| 197 IsolatedContext::GetInstance()->RegisterFileSystemForPath( | |
| 198 fileapi::kFileSystemTypeNativeMedia, path, ®ister_name); | |
| 199 CHECK(!fsid.empty()); | |
| 200 return fsid; | |
| 201 } | |
| 202 | |
| 203 void MediaFileSystemRegistry::RevokeMediaFileSystem(const FilePath& path) { | |
| 204 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 205 | |
| 206 IsolatedContext* isolated_context = IsolatedContext::GetInstance(); | |
| 207 isolated_context->RevokeFileSystemByPath(path); | |
| 208 | |
| 209 for (ChildIdToMediaFSMap::iterator child_it = media_fs_map_.begin(); | |
| 210 child_it != media_fs_map_.end(); | |
| 211 ++child_it) { | |
| 212 MediaPathToFSIDMap& child_map = child_it->second; | |
| 213 MediaPathToFSIDMap::iterator media_path_it = child_map.find(path); | |
| 214 if (media_path_it == child_map.end()) | |
| 215 continue; | |
| 216 | |
| 217 child_map.erase(media_path_it); | |
| 218 } | |
| 219 } | 420 } |
| 220 | 421 |
| 221 } // namespace chrome | 422 } // namespace chrome |
| OLD | NEW |