| 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 #include <vector> |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 dict_value.SetWithoutPathExpansion("deviceId", | 99 dict_value.SetWithoutPathExpansion("deviceId", |
| 100 Value::CreateStringValue(device_id)); | 100 Value::CreateStringValue(device_id)); |
| 101 } | 101 } |
| 102 | 102 |
| 103 std::string json_string; | 103 std::string json_string; |
| 104 base::JSONWriter::Write(&dict_value, &json_string); | 104 base::JSONWriter::Write(&dict_value, &json_string); |
| 105 return json_string; | 105 return json_string; |
| 106 } | 106 } |
| 107 | 107 |
| 108 std::string GetTransientIdForRemovableDeviceId(const std::string& device_id) { | 108 std::string GetTransientIdForRemovableDeviceId(const std::string& device_id) { |
| 109 #if defined(OS_ANDROID) |
| 110 return std::string(); |
| 111 #else |
| 109 using extensions::MediaGalleriesPrivateEventRouter; | 112 using extensions::MediaGalleriesPrivateEventRouter; |
| 110 | 113 |
| 111 if (!MediaStorageUtil::IsRemovableDevice(device_id)) | 114 if (!MediaStorageUtil::IsRemovableDevice(device_id)) |
| 112 return std::string(); | 115 return std::string(); |
| 113 return MediaGalleriesPrivateEventRouter::GetTransientIdForDeviceId(device_id); | 116 return MediaGalleriesPrivateEventRouter::GetTransientIdForDeviceId(device_id); |
| 117 #endif // OS_ANDROID |
| 114 } | 118 } |
| 115 | 119 |
| 116 } // namespace | 120 } // namespace |
| 117 | 121 |
| 118 MediaFileSystemInfo::MediaFileSystemInfo(const std::string& fs_name, | 122 MediaFileSystemInfo::MediaFileSystemInfo(const std::string& fs_name, |
| 119 const FilePath& fs_path, | 123 const FilePath& fs_path, |
| 120 const std::string& filesystem_id) | 124 const std::string& filesystem_id) |
| 121 : name(fs_name), | 125 : name(fs_name), |
| 122 path(fs_path), | 126 path(fs_path), |
| 123 fsid(filesystem_id) { | 127 fsid(filesystem_id) { |
| 124 } | 128 } |
| 125 | 129 |
| 126 MediaFileSystemInfo::MediaFileSystemInfo() {} | 130 MediaFileSystemInfo::MediaFileSystemInfo() {} |
| 127 | 131 |
| 128 #if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) | 132 #if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) |
| 129 // Class to manage MTPDeviceDelegateImpl object for the attached MTP device. | |
| 130 // Refcounted to reuse the same MTP device delegate entry across extensions. | |
| 131 // This class supports WeakPtr (extends SupportsWeakPtr) to expose itself as | |
| 132 // a weak pointer to MediaFileSystemRegistry. | |
| 133 class ScopedMTPDeviceMapEntry | |
| 134 : public base::RefCounted<ScopedMTPDeviceMapEntry>, | |
| 135 public base::SupportsWeakPtr<ScopedMTPDeviceMapEntry> { | |
| 136 public: | |
| 137 // |no_references_callback| is called when the last ScopedMTPDeviceMapEntry | |
| 138 // reference goes away. | |
| 139 ScopedMTPDeviceMapEntry(const FilePath::StringType& device_location, | |
| 140 const base::Closure& no_references_callback) | |
| 141 : device_location_(device_location), | |
| 142 no_references_callback_(no_references_callback) { | |
| 143 BrowserThread::PostTask( | |
| 144 BrowserThread::IO, FROM_HERE, | |
| 145 Bind(&MTPDeviceMapService::AddDelegate, | |
| 146 base::Unretained(MTPDeviceMapService::GetInstance()), | |
| 147 device_location_, | |
| 148 make_scoped_refptr(new MTPDeviceDelegateImpl(device_location)))); | |
| 149 } | |
| 150 | 133 |
| 151 private: | 134 ScopedMTPDeviceMapEntry::ScopedMTPDeviceMapEntry( |
| 152 // Friend declaration for ref counted implementation. | 135 const FilePath::StringType& device_location, |
| 153 friend class base::RefCounted<ScopedMTPDeviceMapEntry>; | 136 const base::Closure& no_references_callback) |
| 137 : device_location_(device_location), |
| 138 delegate_(new MTPDeviceDelegateImpl(device_location)), |
| 139 no_references_callback_(no_references_callback) { |
| 140 BrowserThread::PostTask( |
| 141 BrowserThread::IO, FROM_HERE, |
| 142 Bind(&MTPDeviceMapService::AddDelegate, |
| 143 base::Unretained(MTPDeviceMapService::GetInstance()), |
| 144 device_location_, make_scoped_refptr(delegate_))); |
| 145 } |
| 154 | 146 |
| 155 // Private because this class is ref-counted. | 147 ScopedMTPDeviceMapEntry::~ScopedMTPDeviceMapEntry() { |
| 156 ~ScopedMTPDeviceMapEntry() { | 148 BrowserThread::PostTask( |
| 157 BrowserThread::PostTask( | 149 BrowserThread::IO, FROM_HERE, |
| 158 BrowserThread::IO, FROM_HERE, | 150 Bind(&MTPDeviceMapService::RemoveDelegate, |
| 159 Bind(&MTPDeviceMapService::RemoveDelegate, | 151 base::Unretained(MTPDeviceMapService::GetInstance()), |
| 160 base::Unretained(MTPDeviceMapService::GetInstance()), | 152 device_location_)); |
| 161 device_location_)); | 153 no_references_callback_.Run(); |
| 162 no_references_callback_.Run(); | 154 } |
| 163 } | |
| 164 | 155 |
| 165 // Store the MTP or PTP device location. | 156 #endif // defined(SUPPORT_MTP_DEVICE_FILESYSTEM) |
| 166 const FilePath::StringType device_location_; | |
| 167 | |
| 168 // A callback to call when the last reference of this object goes away. | |
| 169 base::Closure no_references_callback_; | |
| 170 | |
| 171 DISALLOW_COPY_AND_ASSIGN(ScopedMTPDeviceMapEntry); | |
| 172 }; | |
| 173 #endif | |
| 174 | 157 |
| 175 // The main owner of this class is | 158 // The main owner of this class is |
| 176 // |MediaFileSystemRegistry::extension_hosts_map_|, but a callback may | 159 // |MediaFileSystemRegistry::extension_hosts_map_|, but a callback may |
| 177 // temporarily hold a reference. | 160 // temporarily hold a reference. |
| 178 class ExtensionGalleriesHost | 161 class ExtensionGalleriesHost |
| 179 : public base::RefCountedThreadSafe<ExtensionGalleriesHost>, | 162 : public base::RefCountedThreadSafe<ExtensionGalleriesHost>, |
| 180 public content::NotificationObserver { | 163 public content::NotificationObserver { |
| 181 public: | 164 public: |
| 182 // |no_references_callback| is called when the last RenderViewHost reference | 165 // |no_references_callback| is called when the last RenderViewHost reference |
| 183 // goes away. RenderViewHost references are added through ReferenceFromRVH(). | 166 // goes away. RenderViewHost references are added through ReferenceFromRVH(). |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 238 | 221 |
| 239 file_system_context_->RevokeFileSystem(gallery->second.fsid); | 222 file_system_context_->RevokeFileSystem(gallery->second.fsid); |
| 240 pref_id_map_.erase(gallery); | 223 pref_id_map_.erase(gallery); |
| 241 | 224 |
| 242 #if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) | 225 #if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) |
| 243 MediaDeviceEntryReferencesMap::iterator mtp_device_host = | 226 MediaDeviceEntryReferencesMap::iterator mtp_device_host = |
| 244 media_device_map_references_.find(id); | 227 media_device_map_references_.find(id); |
| 245 if (mtp_device_host != media_device_map_references_.end()) | 228 if (mtp_device_host != media_device_map_references_.end()) |
| 246 media_device_map_references_.erase(mtp_device_host); | 229 media_device_map_references_.erase(mtp_device_host); |
| 247 #endif | 230 #endif |
| 231 |
| 232 if (pref_id_map_.empty()) { |
| 233 rph_refs_.clear(); |
| 234 CleanUp(); |
| 235 } |
| 248 } | 236 } |
| 249 | 237 |
| 250 // Indicate that the passed |rvh| will reference the file system ids created | 238 // Indicate that the passed |rvh| will reference the file system ids created |
| 251 // by this class. It is safe to call this multiple times with the same RVH. | 239 // by this class. It is safe to call this multiple times with the same RVH. |
| 252 void ReferenceFromRVH(const content::RenderViewHost* rvh) { | 240 void ReferenceFromRVH(const content::RenderViewHost* rvh) { |
| 253 WebContents* contents = WebContents::FromRenderViewHost(rvh); | 241 WebContents* contents = WebContents::FromRenderViewHost(rvh); |
| 254 if (registrar_.IsRegistered(this, | 242 if (registrar_.IsRegistered(this, |
| 255 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 243 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| 256 content::Source<WebContents>(contents))) { | 244 content::Source<WebContents>(contents))) { |
| 257 return; | 245 return; |
| 258 } | 246 } |
| 259 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 247 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| 260 content::Source<WebContents>(contents)); | 248 content::Source<WebContents>(contents)); |
| 261 registrar_.Add( | 249 registrar_.Add( |
| 262 this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 250 this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| 263 content::Source<NavigationController>(&contents->GetController())); | 251 content::Source<NavigationController>(&contents->GetController())); |
| 264 | 252 |
| 265 RenderProcessHost* rph = contents->GetRenderProcessHost(); | 253 RenderProcessHost* rph = contents->GetRenderProcessHost(); |
| 266 rph_refs_[rph].insert(contents); | 254 rph_refs_[rph].insert(contents); |
| 267 if (rph_refs_[rph].size() == 1) { | 255 if (rph_refs_[rph].size() == 1) { |
| 268 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | 256 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
| 269 content::Source<RenderProcessHost>(rph)); | 257 content::Source<RenderProcessHost>(rph)); |
| 270 } | 258 } |
| 271 } | 259 } |
| 272 | 260 |
| 273 private: | 261 private: |
| 274 typedef std::map<MediaGalleryPrefId, MediaFileSystemInfo> | 262 typedef std::map<MediaGalleryPrefId, MediaFileSystemInfo> |
| 275 PrefIdFsInfoMap; | 263 PrefIdFsInfoMap; |
| 276 #if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) | 264 #if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) |
| 277 typedef std::map<MediaGalleryPrefId, | 265 typedef std::map<MediaGalleryPrefId, |
| 278 scoped_refptr<ScopedMTPDeviceMapEntry> > | 266 scoped_refptr<ScopedMTPDeviceMapEntry> > |
| (...skipping 12 matching lines...) Expand all Loading... |
| 291 #if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) | 279 #if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) |
| 292 DCHECK(media_device_map_references_.empty()); | 280 DCHECK(media_device_map_references_.empty()); |
| 293 #endif | 281 #endif |
| 294 } | 282 } |
| 295 | 283 |
| 296 // NotificationObserver implementation. | 284 // NotificationObserver implementation. |
| 297 virtual void Observe(int type, | 285 virtual void Observe(int type, |
| 298 const content::NotificationSource& source, | 286 const content::NotificationSource& source, |
| 299 const content::NotificationDetails& details) OVERRIDE { | 287 const content::NotificationDetails& details) OVERRIDE { |
| 300 switch (type) { | 288 switch (type) { |
| 301 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { | 289 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: { |
| 302 OnRendererProcessClosed( | 290 OnRendererProcessTerminated( |
| 303 content::Source<RenderProcessHost>(source).ptr()); | 291 content::Source<RenderProcessHost>(source).ptr()); |
| 304 break; | 292 break; |
| 305 } | 293 } |
| 306 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { | 294 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { |
| 307 OnWebContentsDestroyedOrNavigated( | 295 OnWebContentsDestroyedOrNavigated( |
| 308 content::Source<WebContents>(source).ptr()); | 296 content::Source<WebContents>(source).ptr()); |
| 309 break; | 297 break; |
| 310 } | 298 } |
| 311 case content::NOTIFICATION_NAV_ENTRY_COMMITTED: { | 299 case content::NOTIFICATION_NAV_ENTRY_COMMITTED: { |
| 312 NavigationController* controller = | 300 NavigationController* controller = |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 374 MakeJSONFileSystemName(gallery_info.display_name, | 362 MakeJSONFileSystemName(gallery_info.display_name, |
| 375 pref_id, | 363 pref_id, |
| 376 GetTransientIdForRemovableDeviceId(device_id)), | 364 GetTransientIdForRemovableDeviceId(device_id)), |
| 377 path, | 365 path, |
| 378 fsid); | 366 fsid); |
| 379 result.push_back(new_entry); | 367 result.push_back(new_entry); |
| 380 new_galleries.insert(pref_id); | 368 new_galleries.insert(pref_id); |
| 381 pref_id_map_[pref_id] = new_entry; | 369 pref_id_map_[pref_id] = new_entry; |
| 382 } | 370 } |
| 383 | 371 |
| 384 RevokeOldGalleries(new_galleries); | 372 if (result.size() == 0) { |
| 373 rph_refs_.clear(); |
| 374 CleanUp(); |
| 375 } else { |
| 376 RevokeOldGalleries(new_galleries); |
| 377 } |
| 385 | 378 |
| 386 callback.Run(result); | 379 callback.Run(result); |
| 387 } | 380 } |
| 388 | 381 |
| 389 void OnRendererProcessClosed(const RenderProcessHost* rph) { | 382 void OnRendererProcessTerminated(const RenderProcessHost* rph) { |
| 390 RenderProcessHostRefCount::const_iterator rph_info = rph_refs_.find(rph); | 383 RenderProcessHostRefCount::const_iterator rph_info = rph_refs_.find(rph); |
| 391 DCHECK(rph_info != rph_refs_.end()); | 384 DCHECK(rph_info != rph_refs_.end()); |
| 392 // We're going to remove everything from the set, so we make a copy | 385 // We're going to remove everything from the set, so we make a copy |
| 393 // before operating on it. | 386 // before operating on it. |
| 394 std::set<const WebContents*> closed_web_contents = rph_info->second; | 387 std::set<const WebContents*> closed_web_contents = rph_info->second; |
| 395 DCHECK(!closed_web_contents.empty()); | 388 DCHECK(!closed_web_contents.empty()); |
| 396 | 389 |
| 397 for (std::set<const WebContents*>::const_iterator it = | 390 for (std::set<const WebContents*>::const_iterator it = |
| 398 closed_web_contents.begin(); | 391 closed_web_contents.begin(); |
| 399 it != closed_web_contents.end(); | 392 it != closed_web_contents.end(); |
| 400 ++it) { | 393 ++it) { |
| 401 OnWebContentsDestroyedOrNavigated(*it); | 394 OnWebContentsDestroyedOrNavigated(*it); |
| 402 } | 395 } |
| 403 } | 396 } |
| 404 | 397 |
| 405 void OnWebContentsDestroyedOrNavigated(const WebContents* contents) { | 398 void OnWebContentsDestroyedOrNavigated(const WebContents* contents) { |
| 406 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 399 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| 407 content::Source<WebContents>(contents)); | 400 content::Source<WebContents>(contents)); |
| 408 registrar_.Remove( | 401 registrar_.Remove( |
| 409 this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 402 this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| 410 content::Source<NavigationController>(&contents->GetController())); | 403 content::Source<NavigationController>(&contents->GetController())); |
| 411 | 404 |
| 412 RenderProcessHost* rph = contents->GetRenderProcessHost(); | 405 RenderProcessHost* rph = contents->GetRenderProcessHost(); |
| 413 RenderProcessHostRefCount::iterator process_refs = rph_refs_.find(rph); | 406 RenderProcessHostRefCount::iterator process_refs = rph_refs_.find(rph); |
| 414 DCHECK(process_refs != rph_refs_.end()); | 407 DCHECK(process_refs != rph_refs_.end()); |
| 415 process_refs->second.erase(contents); | 408 process_refs->second.erase(contents); |
| 416 if (process_refs->second.empty()) { | 409 if (process_refs->second.empty()) { |
| 417 registrar_.Remove(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | 410 registrar_.Remove(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
| 418 content::Source<RenderProcessHost>(rph)); | 411 content::Source<RenderProcessHost>(rph)); |
| 419 rph_refs_.erase(process_refs); | 412 rph_refs_.erase(process_refs); |
| 420 } | 413 } |
| 421 | 414 |
| 422 if (rph_refs_.empty()) { | 415 if (rph_refs_.empty()) |
| 423 for (PrefIdFsInfoMap::const_iterator it = pref_id_map_.begin(); | 416 CleanUp(); |
| 424 it != pref_id_map_.end(); | 417 } |
| 425 ++it) { | 418 |
| 426 file_system_context_->RevokeFileSystem(it->second.fsid); | 419 void CleanUp() { |
| 427 } | 420 DCHECK(rph_refs_.empty()); |
| 428 pref_id_map_.clear(); | 421 for (PrefIdFsInfoMap::const_iterator it = pref_id_map_.begin(); |
| 422 it != pref_id_map_.end(); |
| 423 ++it) { |
| 424 file_system_context_->RevokeFileSystem(it->second.fsid); |
| 425 } |
| 426 pref_id_map_.clear(); |
| 429 | 427 |
| 430 #if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) | 428 #if defined(SUPPORT_MTP_DEVICE_FILESYSTEM) |
| 431 media_device_map_references_.clear(); | 429 media_device_map_references_.clear(); |
| 432 #endif | 430 #endif |
| 433 | 431 |
| 434 no_references_callback_.Run(); | 432 registrar_.RemoveAll(); |
| 435 } | 433 |
| 434 no_references_callback_.Run(); |
| 436 } | 435 } |
| 437 | 436 |
| 438 // MediaFileSystemRegistry owns |this| and |file_system_context_|, so it's | 437 // MediaFileSystemRegistry owns |this| and |file_system_context_|, so it's |
| 439 // safe to store a raw pointer. | 438 // safe to store a raw pointer. |
| 440 MediaFileSystemContext* file_system_context_; | 439 MediaFileSystemContext* file_system_context_; |
| 441 | 440 |
| 442 // A callback to call when the last RVH reference goes away. | 441 // A callback to call when the last RVH reference goes away. |
| 443 base::Closure no_references_callback_; | 442 base::Closure no_references_callback_; |
| 444 | 443 |
| 445 // A map from the gallery preferences id to the file system information. | 444 // A map from the gallery preferences id to the file system information. |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 547 | 546 |
| 548 for (ExtensionGalleriesHostMap::iterator profile_it = | 547 for (ExtensionGalleriesHostMap::iterator profile_it = |
| 549 extension_hosts_map_.begin(); | 548 extension_hosts_map_.begin(); |
| 550 profile_it != extension_hosts_map_.end(); | 549 profile_it != extension_hosts_map_.end(); |
| 551 ++profile_it) { | 550 ++profile_it) { |
| 552 MediaGalleriesPreferences* preferences = GetPreferences(profile_it->first); | 551 MediaGalleriesPreferences* preferences = GetPreferences(profile_it->first); |
| 553 preferences->AddGallery(id, name, FilePath(), false /*not user added*/); | 552 preferences->AddGallery(id, name, FilePath(), false /*not user added*/); |
| 554 } | 553 } |
| 555 } | 554 } |
| 556 | 555 |
| 556 size_t MediaFileSystemRegistry::GetExtensionHostCountForTests() const { |
| 557 return extension_hosts_map_.size(); |
| 558 } |
| 559 |
| 557 void MediaFileSystemRegistry::OnRemovableStorageDetached( | 560 void MediaFileSystemRegistry::OnRemovableStorageDetached( |
| 558 const std::string& id) { | 561 const std::string& id) { |
| 559 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 562 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 560 | 563 |
| 561 // Since revoking a gallery in the ExtensionGalleriesHost may cause it | 564 // Since revoking a gallery in the ExtensionGalleriesHost may cause it |
| 562 // to be removed from the map and therefore invalidate any iterator pointing | 565 // to be removed from the map and therefore invalidate any iterator pointing |
| 563 // to it, this code first copies all the invalid gallery ids and the | 566 // to it, this code first copies all the invalid gallery ids and the |
| 564 // extension hosts in which they may appear (per profile) and revoked it in | 567 // extension hosts in which they may appear (per profile) and revoked it in |
| 565 // a second step. | 568 // a second step. |
| 566 std::vector<InvalidatedGalleriesInfo> invalid_galleries_info; | 569 std::vector<InvalidatedGalleriesInfo> invalid_galleries_info; |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 753 | 756 |
| 754 PrefChangeRegistrarMap::iterator pref_it = | 757 PrefChangeRegistrarMap::iterator pref_it = |
| 755 pref_change_registrar_map_.find(profile); | 758 pref_change_registrar_map_.find(profile); |
| 756 DCHECK(pref_it != pref_change_registrar_map_.end()); | 759 DCHECK(pref_it != pref_change_registrar_map_.end()); |
| 757 delete pref_it->second; | 760 delete pref_it->second; |
| 758 pref_change_registrar_map_.erase(pref_it); | 761 pref_change_registrar_map_.erase(pref_it); |
| 759 } | 762 } |
| 760 } | 763 } |
| 761 | 764 |
| 762 } // namespace chrome | 765 } // namespace chrome |
| OLD | NEW |