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