| 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 | 10 |
| 11 #include "base/file_path.h" | 11 #include "base/file_path.h" |
| 12 #include "base/path_service.h" | 12 #include "base/path_service.h" |
| 13 #include "base/system_monitor/system_monitor.h" | 13 #include "base/system_monitor/system_monitor.h" |
| 14 #include "base/utf_string_conversions.h" | 14 #include "base/utf_string_conversions.h" |
| 15 #include "chrome/browser/media_gallery/media_storage_util.h" | 15 #include "chrome/browser/media_gallery/media_storage_util.h" |
| 16 #include "chrome/common/chrome_paths.h" | 16 #include "chrome/common/chrome_paths.h" |
| 17 #include "chrome/common/extensions/extension_constants.h" | 17 #include "chrome/common/extensions/extension_constants.h" |
| 18 #include "chrome/common/extensions/extension.h" | 18 #include "chrome/common/extensions/extension.h" |
| 19 #include "content/public/browser/browser_thread.h" | 19 #include "content/public/browser/browser_thread.h" |
| 20 #include "content/public/browser/notification_source.h" | 20 #include "content/public/browser/notification_source.h" |
| 21 #include "content/public/browser/notification_types.h" | 21 #include "content/public/browser/notification_types.h" |
| 22 #include "content/public/browser/render_process_host.h" | 22 #include "content/public/browser/render_process_host.h" |
| 23 #include "webkit/fileapi/file_system_types.h" | 23 #include "webkit/fileapi/file_system_types.h" |
| 24 #include "webkit/fileapi/isolated_context.h" | 24 #include "webkit/fileapi/isolated_context.h" |
| 25 #include "webkit/fileapi/media/media_file_system_config.h" | 25 #include "webkit/fileapi/media/media_file_system_config.h" |
| 26 | 26 |
| 27 #if defined(SUPPORT_MEDIA_FILESYSTEM) | 27 #if defined(SUPPORT_MEDIA_FILESYSTEM) |
| 28 #include "webkit/fileapi/media/media_device_map_service.h" | 28 #include "webkit/fileapi/media/media_device_map_service.h" |
| 29 | |
| 30 using fileapi::MediaDeviceMapService; | |
| 31 #endif | 29 #endif |
| 32 | 30 |
| 33 namespace chrome { | 31 namespace chrome { |
| 34 | 32 |
| 35 static base::LazyInstance<MediaFileSystemRegistry>::Leaky | 33 static base::LazyInstance<MediaFileSystemRegistry>::Leaky |
| 36 g_media_file_system_registry = LAZY_INSTANCE_INITIALIZER; | 34 g_media_file_system_registry = LAZY_INSTANCE_INITIALIZER; |
| 37 | 35 |
| 38 using base::SystemMonitor; | 36 using base::SystemMonitor; |
| 39 using content::BrowserThread; | 37 using content::BrowserThread; |
| 40 using content::RenderProcessHost; | 38 using content::RenderProcessHost; |
| 41 using fileapi::IsolatedContext; | 39 using fileapi::IsolatedContext; |
| 42 | 40 |
| 43 namespace { | 41 namespace { |
| 44 | 42 |
| 45 bool IsGalleryPermittedForExtension(const extensions::Extension& extension, | 43 FilePath DeviceIdToPath(std::string device_id) { |
| 46 const FilePath::StringType& location) { | 44 // TODO(vandebo) This needs to be cleaned up. We need a device manager |
| 47 if (extension.HasAPIPermission( | 45 // type class that will handle this kind of thing. Right now |
| 48 extensions::APIPermission::kMediaGalleriesAllGalleries)) { | 46 // MediaFileSystemRegistry::GetDeviceIdFromPath just turns the path into |
| 49 return true; | 47 // a string, so for now we can just go the other way. |
| 50 } | 48 return FilePath(device_id); |
| 51 // TODO(vandebo) Check with prefs for permission to this gallery. | |
| 52 return false; | |
| 53 } | 49 } |
| 54 | 50 |
| 51 std::string MediaFileSystemRegistry::RegisterPathAsFileSystem( |
| 52 const SystemMonitor::MediaDeviceType& device_type, |
| 53 std::string device_id, |
| 54 const FilePath& relative_path) { |
| 55 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 56 |
| 57 |
| 58 IsolatedContext* isolated_context = IsolatedContext::GetInstance(); |
| 59 if (device_type == SystemMonitor::TYPE_PATH) { |
| 60 FilePath path = DeviceIdToPath(device_id).Append(relative_path); |
| 61 // Sanity checks for |path|. |
| 62 CHECK(path.IsAbsolute()); |
| 63 CHECK(!path.ReferencesParent()); |
| 64 const std::string fsid = isolated_context->RegisterFileSystemForPath( |
| 65 fileapi::kFileSystemTypeNativeMedia, |
| 66 path, |
| 67 extension_misc::kMediaFileSystemPathPart); |
| 68 CHECK(!fsid.empty()); |
| 69 return fsid; |
| 70 } |
| 71 |
| 72 // TODO(vandebo) handle device_type == case SystemMonitor::TYPE_MTP. |
| 73 NOTREACHED(); |
| 74 return std::string(); |
| 75 } |
| 76 |
| 77 class ExtensionGalleriesHost : public content::NotificationObserver { |
| 78 public: |
| 79 typedef base::Callback<void(void)> NoReferenecesCallback; |
| 80 |
| 81 explicit ExtensionGalleriesHost(const NoReferencesCallback& callback) |
| 82 : callback_(callback) { |
| 83 } |
| 84 virtual ~ExtensionGalleriesHost() { |
| 85 DCHECK(rph_refs_.empty()); |
| 86 DCHECK(pref_id_map_.empty()); |
| 87 } |
| 88 |
| 89 // Lookup the galleries for this extension, turn those into file system ids |
| 90 // and return the information needed for the renderer to create those file |
| 91 // system objects. |
| 92 std::vector<MediaFSInfo> GetMediaFileSystems( |
| 93 const MediaGalleryPrefIdSet& galleries, |
| 94 const MediaGalleriesPrefInfoMap& galleries_info) { |
| 95 std::vector<MediaFSInfo> result; |
| 96 for (std::set<MediaGalleryPrefId>::const_iterator id = galleries.begin(); |
| 97 id != galleries.end(); |
| 98 ++id) { |
| 99 PrefIdFsInfoMap::const_iterator existing_info = pref_id_map_.find(id); |
| 100 if (existing_info != pref_id_map_.end()) { |
| 101 result.append(*existing_info); |
| 102 continue; |
| 103 } |
| 104 // TODO(vandebo): For MTP, path is empty. |
| 105 MediaFsInfo new_entry; |
| 106 new_entry.name = galleries_info[*id].display_name; |
| 107 new_entry.path = FilePath path = DeviceIdToPath( |
| 108 galleries_info[*id].device_id).Append(galleries_info[*id].path); |
| 109 // TODO(vandebo): Get type out of galleries_info. |
| 110 new_entry.fsid = RegisterPathAsFileSystem(SystemMonitor::TYPE_PATH, |
| 111 galleries_info[*id].device_id, |
| 112 galleries_info[*id].path); |
| 113 result.append(new_entry); |
| 114 pref_id_map_[pref_id] = new_entry; |
| 115 } |
| 116 return result; |
| 117 } |
| 118 |
| 119 // If this extension has created a file system id for the given gallery |
| 120 // then revoke it. |
| 121 void RevokeGalleryByPrefId(MediaGalleryPrefId id) { |
| 122 PrefIdFsInfoMap::iterator gallery = pref_id_map_.find(id); |
| 123 if (gallery == pref_id_map_.end()) |
| 124 return; |
| 125 |
| 126 IsolatedContext* isolated_context = IsolatedContext::GetInstance(); |
| 127 isolated_context->RevokeFileSystem(gallery->fsid); |
| 128 |
| 129 pref_id_map_.erase(gallery); |
| 130 } |
| 131 |
| 132 // Indicate that the passed render process will reference the file system |
| 133 // ids created by this class. It is safe to call this multiple times with |
| 134 // the same RVH. |
| 135 void ReferenceFromRVH(const content::RenderViewHost* rvh) { |
| 136 WebContents* contents = WebContents::FromRenderViewHost(rvh); |
| 137 if (registrar_.IsRegistered(this, |
| 138 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| 139 content::Source<WebContents>(contents))) { |
| 140 return; |
| 141 } |
| 142 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| 143 content::Source<WebContents>(contents)); |
| 144 registrar_.Add( |
| 145 this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| 146 content::Source<NavigationController>(&contents->GetController())); |
| 147 |
| 148 content::RenderProcessHost* rph = contents->GetRenderProcessHost(); |
| 149 rph_refs_[rph].insert(contents); |
| 150 if (rph_refs[rph].size() == 1) { |
| 151 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, |
| 152 content::Source<content::RenderProcessHost>(rph)); |
| 153 } |
| 154 } |
| 155 |
| 156 // NotificationObserver implementation. |
| 157 virtual void Observe(int type, |
| 158 const NotificationSource& source, |
| 159 const NotificationDetails& details) { |
| 160 switch (type) { |
| 161 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { |
| 162 OnRendererProcessClosed( |
| 163 content::Source<content::RenderProcessHost>(source).ptr()); |
| 164 break; |
| 165 } |
| 166 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { |
| 167 OnWebContentsDestroyedOrNavigated( |
| 168 content::Source<WebContents>(source).ptr()); |
| 169 break; |
| 170 } |
| 171 case content::NOTIFICATION_NAV_ENTRY_COMMITTED: { |
| 172 NavigationController* controller = |
| 173 content::Source<NavigationController>(source).ptr(); |
| 174 WebContents* contents = controller->GetWebContents(); |
| 175 OnWebContentsDestroyedOrNavigated(contents); |
| 176 break; |
| 177 } |
| 178 default: { |
| 179 NOTREACHED(); |
| 180 break; |
| 181 } |
| 182 } |
| 183 } |
| 184 |
| 185 private: |
| 186 typedef std::map<MediaGalleriesPrefId, MediaFSInfo> PrefIdFsInfoMap; |
| 187 typedef std::map<const content::RenderProcessHost*, |
| 188 std::set<const WebContent*> > RenderProcessHostRefCount; |
| 189 |
| 190 void OnRendererProcessClosed(const contents::RenderProcessHost* rph) { |
| 191 std::set<const Content*> dead_rvhs = rph_refs_[rph]; |
| 192 DCHECK(!dead_rvhs.empty()); |
| 193 |
| 194 for (std::set<const Content*>::const_iterator it = dead_rvhs.begin(); |
| 195 it != dead_rvhs.end(); |
| 196 ++it) { |
| 197 OnWebContentsDestroyedOrNavigated(*it); |
| 198 } |
| 199 DCHECK(rph_refs_.find(rph) == rph_refs_.end()); |
| 200 } |
| 201 |
| 202 void OnWebContentsDestroyedOrNavigated(const WebContents* contents) { |
| 203 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| 204 content::Source<WebContents>(contents)); |
| 205 registrar_.Remove( |
| 206 this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| 207 content::Source<NavigationController>(&contents->GetController())); |
| 208 |
| 209 content::RenderProcessHost* rph = contents->GetRenderProcessHost(); |
| 210 rph_refs_[rph].erase(contents); |
| 211 if (rph_refs_[rph].empty()) { |
| 212 registrar_.Remove(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, |
| 213 content::Source<content::RenderProcessHost>(rph)); |
| 214 rph_refs_.erase(rph); |
| 215 } |
| 216 |
| 217 if (rph_refs_.empty()) { |
| 218 IsolatedContext* isolated_context = IsolatedContext::GetInstance(); |
| 219 for (PrefIdFsInfoMap::const_iterator it = pref_id_map_.begin(); |
| 220 it != pref_id_map_.end(); |
| 221 ++it) { |
| 222 isolated_context->RevokeFileSystem(it->fsid); |
| 223 } |
| 224 pref_id_map_.clear(); |
| 225 callback_.Run(); |
| 226 } |
| 227 } |
| 228 |
| 229 // A callback to call when the last RVH reference goes away. |
| 230 const NoReferencesCallback& callback_; |
| 231 |
| 232 // A map from the gallery preferences id to the file system id. |
| 233 PrefIdFsInfoMap pref_id_map_; |
| 234 |
| 235 // The set of render processes and web contents that may have references to |
| 236 // the file system ids this instance manages. |
| 237 RenderProcessHostRefCount rph_refs_; |
| 238 |
| 239 // A registrar for listening notifications. |
| 240 content::NotificationRegistrar registrar_; |
| 241 |
| 242 DISALLOW_COPY_AND_ASSIGN(ExtensionGalleriesHost); |
| 243 }; |
| 244 |
| 55 } // namespace | 245 } // namespace |
| 56 | 246 |
| 57 | 247 |
| 58 /****************** | 248 /****************** |
| 59 * Public methods | 249 * Public methods |
| 60 ******************/ | 250 ******************/ |
| 61 | 251 |
| 62 // static | 252 // static |
| 63 MediaFileSystemRegistry* MediaFileSystemRegistry::GetInstance() { | 253 MediaFileSystemRegistry* MediaFileSystemRegistry::GetInstance() { |
| 64 return g_media_file_system_registry.Pointer(); | 254 return g_media_file_system_registry.Pointer(); |
| 65 } | 255 } |
| 66 | 256 |
| 67 std::vector<MediaFileSystemRegistry::MediaFSInfo> | 257 std::vector<MediaFileSystemRegistry::MediaFSInfo> |
| 68 MediaFileSystemRegistry::GetMediaFileSystemsForExtension( | 258 MediaFileSystemRegistry::GetMediaFileSystemsForExtension( |
| 69 const content::RenderProcessHost* rph, | 259 const content::RenderViewHost* rvh, |
| 70 const extensions::Extension& extension) { | 260 const extensions::Extension* extension) { |
| 71 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 261 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 72 | 262 |
| 73 std::vector<MediaFSInfo> results; | 263 Profile* profile = |
| 74 std::pair<ChildIdToMediaFSMap::iterator, bool> ret = | 264 Profile::FromBrowserContext(rvh->GetProcess()->GetBrowserContext()); |
| 75 media_fs_map_.insert(std::make_pair(rph, MediaPathToFSIDMap())); | 265 MediaGalleriesPreferences* preferences = |
| 76 ChildIdToMediaFSMap::iterator& child_it = ret.first; | 266 MediaGalleriesPreferencesFactory::GetForProfile(profile); |
| 77 if (ret.second) { | 267 MediaGalleryPrefIdSet galleries = |
| 78 // Never seen a GetMediaFileSystems call from this RPH. Initialize its | 268 preferences->GalleriesForExtension(extension); |
| 79 // file system mappings. | 269 if (galleries.empty()) |
| 80 RegisterForRPHGoneNotifications(rph); | 270 return std::vector<MediaFileSystemRegistry::MediaFSInfo>(); |
| 81 FilePath pictures_path; | 271 |
| 82 // TODO(vandebo) file system galleries need a unique id as well. | 272 ExtensionGalleriesHost* extension_host = |
| 83 if (PathService::Get(chrome::DIR_USER_PICTURES, &pictures_path) && | 273 extension_host_map[profile][extension].get(); |
| 84 IsGalleryPermittedForExtension(extension, pictures_path.value())) { | 274 if (!extension_host) { |
| 85 std::string fsid = RegisterPathAsFileSystem(pictures_path); | 275 extension_host_map_[profile][extension].reset(new ExtensionGalleriesHost( |
| 86 child_it->second.insert(std::make_pair(pictures_path, fsid)); | 276 *extension, |
| 87 } | 277 base::Bind(&MediaFileSystemRegistry::OnExtensionGalleriesHostEmpty, |
| 278 base::Unretained(this), profile, extension))); |
| 279 extension_host = extension_host_map[profile][extension].get(); |
| 88 } | 280 } |
| 281 extension_host->ReferenceFromRVH(rvh); |
| 89 | 282 |
| 90 // TODO(thestig) Handle overlap between devices and media directories. | 283 return extension_host->GetMediaFileSystems(galleries, |
| 91 SystemMonitor* monitor = SystemMonitor::Get(); | 284 preferences->known_galleries()); |
| 92 const std::vector<SystemMonitor::MediaDeviceInfo> media_devices = | |
| 93 monitor->GetAttachedMediaDevices(); | |
| 94 for (size_t i = 0; i < media_devices.size(); ++i) { | |
| 95 MediaStorageUtil::Type type; | |
| 96 MediaStorageUtil::CrackDeviceId(media_devices[i].unique_id, &type, NULL); | |
| 97 // TODO(vandebo) Handle MTP devices. | |
| 98 if (type != MediaStorageUtil::USB_MTP && | |
| 99 IsGalleryPermittedForExtension(extension, media_devices[i].location)) { | |
| 100 device_id_map_.insert(std::make_pair(media_devices[i].unique_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 } | 285 } |
| 121 | 286 |
| 122 void MediaFileSystemRegistry::OnMediaDeviceDetached(const std::string& id) { | 287 void MediaFileSystemRegistry::OnMediaDeviceDetached(const std::string& id) { |
| 123 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 288 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 124 | 289 |
| 125 DeviceIdToInfoMap::iterator it = device_id_map_.find(id); | 290 // Since revoking a gallery in the ExtensionGalleriesHost may cause it |
| 126 if (it == device_id_map_.end()) | 291 // to be removed from the map and therefore invalidate any iterator pointing |
| 127 return; | 292 // to it, we first make a list of all the ExtensionGalleriesHost*, pref_id |
| 293 // pairs to invalidate and then invalidate them in a second step. |
| 294 struct InvalidatedGallery { |
| 295 ExtensionGalleriesHost* extension_host; |
| 296 MediaGalleriesPrefId pref_id; |
| 297 }; |
| 298 std::vector<InvalidatedGallery> invalidated_galleries; |
| 128 | 299 |
| 129 FilePath path(it->second.location); | 300 for (ExtensionGalleriesHostMap::const_iterator extension_host_map = |
| 130 RevokeMediaFileSystem(path); | 301 extension_host_map_.begin(); |
| 131 device_id_map_.erase(it); | 302 extension_host_map != extension_host_map_.end(); |
| 132 } | 303 ++extension_host_map) { |
| 304 MediaGalleriesPreferences* preferences = |
| 305 MediaGalleriesPreferencesFactory::GetForProfile( |
| 306 extension_host_map.first); |
| 307 MediaGalleryPrefIdSet detached_galleries = |
| 308 preferences->LookUpGalleriesByDeviceId(id); |
| 309 for (ExtensionHostMap::const_iterator extension_host = |
| 310 extension_host_map.second.begin(); |
| 311 extension_host_map.second.end(); |
| 312 ++extension_host) { |
| 313 for (MediaGalleryPrefIdSet::const_iterator pref_id = |
| 314 detached_galleries.begin(); |
| 315 pref_id != detached_galleries.end(); |
| 316 ++pref_id) { |
| 317 InvalidatedGallery gallery; |
| 318 gallery.extension_host = extesion_host.second.get(); |
| 319 gallery.pref_id = *pref_id; |
| 320 invalidated_galleries.push_back(gallery); |
| 321 } |
| 322 } |
| 323 } |
| 133 | 324 |
| 134 void MediaFileSystemRegistry::Observe( | 325 for (std::vector<InvalidatedGallery>::const_iterator it = |
| 135 int type, | 326 invalidated_galleries.begin(); |
| 136 const content::NotificationSource& source, | 327 it != invalidated_galleries.end(); |
| 137 const content::NotificationDetails& details) { | 328 ++it) { |
| 138 DCHECK(type == content::NOTIFICATION_RENDERER_PROCESS_CLOSED || | 329 it->extension_host->RevokeGalleryByPrefId(it->pref_id); |
| 139 type == content::NOTIFICATION_RENDERER_PROCESS_TERMINATED); | 330 } |
| 140 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 331 |
| 141 const RenderProcessHost* rph = | 332 // TODO(kmadhusu, vandebo): Clean up this code. http://crbug.com/140340. |
| 142 content::Source<content::RenderProcessHost>(source).ptr(); | 333 // FIXME - from the device id, we need the device location. |
| 143 ChildIdToMediaFSMap::iterator child_it = media_fs_map_.find(rph); | 334 #if defined(SUPPORT_MEDIA_FILESYSTEM) |
| 144 CHECK(child_it != media_fs_map_.end()); | 335 //fileapi::MediaDeviceMapService::GetInstance()->RemoveMediaDevice( |
| 145 // No need to revoke the isolated file systems. The RPH will do that. | 336 // device_location); |
| 146 media_fs_map_.erase(child_it); | 337 #endif |
| 147 UnregisterForRPHGoneNotifications(rph); | |
| 148 } | 338 } |
| 149 | 339 |
| 150 std::string MediaFileSystemRegistry::GetDeviceIdFromPath( | 340 std::string MediaFileSystemRegistry::GetDeviceIdFromPath( |
| 151 const FilePath& path) const { | 341 const FilePath& path) const { |
| 152 // TODO(vandebo) Do something better here, at least iterate system monitor | 342 // TODO(vandebo) Do something better here, at least iterate system monitor |
| 153 // attached media devices looking for a match. If not, return the path. | 343 // attached media devices looking for a match. If not, return the path. |
| 154 return path.AsUTF8Unsafe(); | 344 return path.AsUTF8Unsafe(); |
| 155 } | 345 } |
| 156 | 346 |
| 157 /****************** | 347 /****************** |
| 158 * Private methods | 348 * Private methods |
| 159 ******************/ | 349 ******************/ |
| 160 | 350 |
| 161 MediaFileSystemRegistry::MediaFileSystemRegistry() { | 351 MediaFileSystemRegistry::MediaFileSystemRegistry() { |
| 162 // SystemMonitor may be NULL in unit tests. | 352 // SystemMonitor may be NULL in unit tests. |
| 163 SystemMonitor* system_monitor = SystemMonitor::Get(); | 353 SystemMonitor* system_monitor = SystemMonitor::Get(); |
| 164 if (system_monitor) | 354 if (system_monitor) |
| 165 system_monitor->AddDevicesChangedObserver(this); | 355 system_monitor->AddDevicesChangedObserver(this); |
| 166 } | 356 } |
| 167 | 357 |
| 168 MediaFileSystemRegistry::~MediaFileSystemRegistry() { | 358 MediaFileSystemRegistry::~MediaFileSystemRegistry() { |
| 169 // SystemMonitor may be NULL in unit tests. | 359 // SystemMonitor may be NULL in unit tests. |
| 170 SystemMonitor* system_monitor = SystemMonitor::Get(); | 360 SystemMonitor* system_monitor = SystemMonitor::Get(); |
| 171 if (system_monitor) | 361 if (system_monitor) |
| 172 system_monitor->RemoveDevicesChangedObserver(this); | 362 system_monitor->RemoveDevicesChangedObserver(this); |
| 173 } | 363 } |
| 174 | 364 |
| 175 void MediaFileSystemRegistry::RegisterForRPHGoneNotifications( | 365 void MediaFileSystemRegistry::OnExtensionGalleriesHostEmpty( |
| 176 const content::RenderProcessHost* rph) { | 366 const Profile* profile, |
| 177 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | 367 const extensions::Extension* extension) { |
| 178 content::Source<RenderProcessHost>(rph)); | 368 ExtensionHostMap extension_hosts = extension_host_map_[profile]; |
| 179 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | 369 DCHECK(!extension_hosts.empty()); |
| 180 content::Source<RenderProcessHost>(rph)); | 370 ExtensionHostMap::size_type erase_count = extension_hosts.erase(extension); |
| 181 } | 371 DCHECK_EQ(1, erase_count); |
| 182 | 372 if (extension_hosts.empty()) |
| 183 void MediaFileSystemRegistry::UnregisterForRPHGoneNotifications( | 373 extension_host_map_.erase(profile); |
| 184 const content::RenderProcessHost* rph) { | |
| 185 registrar_.Remove(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | |
| 186 content::Source<RenderProcessHost>(rph)); | |
| 187 registrar_.Remove(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | |
| 188 content::Source<RenderProcessHost>(rph)); | |
| 189 } | |
| 190 | |
| 191 std::string MediaFileSystemRegistry::RegisterPathAsFileSystem( | |
| 192 const FilePath& path) { | |
| 193 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 194 | |
| 195 // Sanity checks for |path|. | |
| 196 CHECK(path.IsAbsolute()); | |
| 197 CHECK(!path.ReferencesParent()); | |
| 198 | |
| 199 // The directory name is not exposed to the js layer and we simply use | |
| 200 // a fixed name (as we only register a single directory per file system). | |
| 201 std::string register_name(extension_misc::kMediaFileSystemPathPart); | |
| 202 const std::string fsid = | |
| 203 IsolatedContext::GetInstance()->RegisterFileSystemForPath( | |
| 204 fileapi::kFileSystemTypeNativeMedia, path, ®ister_name); | |
| 205 CHECK(!fsid.empty()); | |
| 206 return fsid; | |
| 207 } | |
| 208 | |
| 209 void MediaFileSystemRegistry::RevokeMediaFileSystem(const FilePath& path) { | |
| 210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 211 | |
| 212 IsolatedContext* isolated_context = IsolatedContext::GetInstance(); | |
| 213 isolated_context->RevokeFileSystemByPath(path); | |
| 214 | |
| 215 for (ChildIdToMediaFSMap::iterator child_it = media_fs_map_.begin(); | |
| 216 child_it != media_fs_map_.end(); | |
| 217 ++child_it) { | |
| 218 MediaPathToFSIDMap& child_map = child_it->second; | |
| 219 MediaPathToFSIDMap::iterator media_path_it = child_map.find(path); | |
| 220 if (media_path_it == child_map.end()) | |
| 221 continue; | |
| 222 | |
| 223 child_map.erase(media_path_it); | |
| 224 } | |
| 225 } | 374 } |
| 226 | 375 |
| 227 } // namespace chrome | 376 } // namespace chrome |
| OLD | NEW |