volume_manager.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/chromeos/file_manager/volume_manager.h" 6 7#include "base/basictypes.h" 8#include "base/bind.h" 9#include "base/callback.h" 10#include "base/command_line.h" 11#include "base/files/file_path.h" 12#include "base/logging.h" 13#include "base/memory/singleton.h" 14#include "base/prefs/pref_service.h" 15#include "chrome/browser/chromeos/drive/drive_integration_service.h" 16#include "chrome/browser/chromeos/drive/file_errors.h" 17#include "chrome/browser/chromeos/drive/file_system_interface.h" 18#include "chrome/browser/chromeos/drive/file_system_util.h" 19#include "chrome/browser/chromeos/file_manager/mounted_disk_monitor.h" 20#include "chrome/browser/chromeos/file_manager/path_util.h" 21#include "chrome/browser/chromeos/file_manager/volume_manager_factory.h" 22#include "chrome/browser/chromeos/file_manager/volume_manager_observer.h" 23#include "chrome/browser/chromeos/profiles/profile_helper.h" 24#include "chrome/browser/local_discovery/storage/privet_filesystem_constants.h" 25#include "chrome/browser/profiles/profile.h" 26#include "chrome/common/chrome_switches.h" 27#include "chrome/common/pref_names.h" 28#include "chromeos/dbus/cros_disks_client.h" 29#include "chromeos/disks/disk_mount_manager.h" 30#include "content/public/browser/browser_context.h" 31#include "content/public/browser/browser_thread.h" 32#include "webkit/browser/fileapi/external_mount_points.h" 33 34namespace file_manager { 35namespace { 36 37// Registers |path| as the "Downloads" folder to the FileSystem API backend. 38// If another folder is already mounted. It revokes and overrides the old one. 39bool RegisterDownloadsMountPoint(Profile* profile, const base::FilePath& path) { 40 // Although we show only profile's own "Downloads" folder in Files.app, 41 // in the backend we need to mount all profile's download directory globally. 42 // Otherwise, Files.app cannot support cross-profile file copies, etc. 43 // For this reason, we need to register to the global GetSystemInstance(). 44 const std::string mount_point_name = 45 file_manager::util::GetDownloadsMountPointName(profile); 46 fileapi::ExternalMountPoints* const mount_points = 47 fileapi::ExternalMountPoints::GetSystemInstance(); 48 49 // In some tests we want to override existing Downloads mount point, so we 50 // first revoke the existing mount point (if any). 51 mount_points->RevokeFileSystem(mount_point_name); 52 return mount_points->RegisterFileSystem( 53 mount_point_name, fileapi::kFileSystemTypeNativeLocal, 54 fileapi::FileSystemMountOption(), path); 55} 56 57// Finds the path register as the "Downloads" folder to FileSystem API backend. 58// Returns false if it is not registered. 59bool FindDownloadsMountPointPath(Profile* profile, base::FilePath* path) { 60 const std::string mount_point_name = 61 util::GetDownloadsMountPointName(profile); 62 fileapi::ExternalMountPoints* const mount_points = 63 fileapi::ExternalMountPoints::GetSystemInstance(); 64 65 return mount_points->GetRegisteredPath(mount_point_name, path); 66} 67 68// Called on completion of MarkCacheFileAsUnmounted. 69void OnMarkCacheFileAsUnmounted(drive::FileError error) { 70 // Do nothing. 71} 72 73VolumeType MountTypeToVolumeType( 74 chromeos::MountType type) { 75 switch (type) { 76 case chromeos::MOUNT_TYPE_INVALID: 77 // We don't expect this value, but list here, so that when any value 78 // is added to the enum definition but this is not edited, the compiler 79 // warns it. 80 break; 81 case chromeos::MOUNT_TYPE_DEVICE: 82 return VOLUME_TYPE_REMOVABLE_DISK_PARTITION; 83 case chromeos::MOUNT_TYPE_ARCHIVE: 84 return VOLUME_TYPE_MOUNTED_ARCHIVE_FILE; 85 } 86 87 NOTREACHED(); 88 return VOLUME_TYPE_DOWNLOADS_DIRECTORY; 89} 90 91// Returns a string representation of the given volume type. 92std::string VolumeTypeToString(VolumeType type) { 93 switch (type) { 94 case VOLUME_TYPE_GOOGLE_DRIVE: 95 return "drive"; 96 case VOLUME_TYPE_DOWNLOADS_DIRECTORY: 97 return "downloads"; 98 case VOLUME_TYPE_REMOVABLE_DISK_PARTITION: 99 return "removable"; 100 case VOLUME_TYPE_MOUNTED_ARCHIVE_FILE: 101 return "archive"; 102 case VOLUME_TYPE_CLOUD_DEVICE: 103 return "cloud_device"; 104 } 105 NOTREACHED(); 106 return ""; 107} 108 109// Generates a unique volume ID for the given volume info. 110std::string GenerateVolumeId(const VolumeInfo& volume_info) { 111 // For the same volume type, base names are unique, as mount points are 112 // flat for the same volume type. 113 return (VolumeTypeToString(volume_info.type) + ":" + 114 volume_info.mount_path.BaseName().AsUTF8Unsafe()); 115} 116 117// Returns the VolumeInfo for Drive file system. 118VolumeInfo CreateDriveVolumeInfo(Profile* profile) { 119 const base::FilePath& drive_path = 120 drive::util::GetDriveMountPointPath(profile); 121 122 VolumeInfo volume_info; 123 volume_info.type = VOLUME_TYPE_GOOGLE_DRIVE; 124 volume_info.device_type = chromeos::DEVICE_TYPE_UNKNOWN; 125 volume_info.source_path = drive_path; 126 volume_info.mount_path = drive_path; 127 volume_info.mount_condition = chromeos::disks::MOUNT_CONDITION_NONE; 128 volume_info.is_parent = false; 129 volume_info.is_read_only = false; 130 volume_info.volume_id = GenerateVolumeId(volume_info); 131 return volume_info; 132} 133 134VolumeInfo CreateDownloadsVolumeInfo( 135 const base::FilePath& downloads_path) { 136 VolumeInfo volume_info; 137 volume_info.type = VOLUME_TYPE_DOWNLOADS_DIRECTORY; 138 volume_info.device_type = chromeos::DEVICE_TYPE_UNKNOWN; 139 // Keep source_path empty. 140 volume_info.mount_path = downloads_path; 141 volume_info.mount_condition = chromeos::disks::MOUNT_CONDITION_NONE; 142 volume_info.is_parent = false; 143 volume_info.is_read_only = false; 144 volume_info.volume_id = GenerateVolumeId(volume_info); 145 return volume_info; 146} 147 148VolumeInfo CreateVolumeInfoFromMountPointInfo( 149 const chromeos::disks::DiskMountManager::MountPointInfo& mount_point, 150 const chromeos::disks::DiskMountManager::Disk* disk) { 151 VolumeInfo volume_info; 152 volume_info.type = MountTypeToVolumeType(mount_point.mount_type); 153 volume_info.source_path = base::FilePath(mount_point.source_path); 154 volume_info.mount_path = base::FilePath(mount_point.mount_path); 155 volume_info.mount_condition = mount_point.mount_condition; 156 if (disk) { 157 volume_info.device_type = disk->device_type(); 158 volume_info.system_path_prefix = 159 base::FilePath(disk->system_path_prefix()); 160 volume_info.drive_label = disk->drive_label(); 161 volume_info.is_parent = disk->is_parent(); 162 volume_info.is_read_only = disk->is_read_only(); 163 } else { 164 volume_info.device_type = chromeos::DEVICE_TYPE_UNKNOWN; 165 volume_info.is_parent = false; 166 volume_info.is_read_only = 167 (mount_point.mount_type == chromeos::MOUNT_TYPE_ARCHIVE); 168 } 169 volume_info.volume_id = GenerateVolumeId(volume_info); 170 171 return volume_info; 172} 173 174VolumeInfo CreatePrivetVolumeInfo( 175 const local_discovery::PrivetVolumeLister::VolumeInfo& privet_volume_info) { 176 VolumeInfo volume_info; 177 volume_info.type = VOLUME_TYPE_CLOUD_DEVICE; 178 volume_info.mount_path = privet_volume_info.volume_path; 179 volume_info.mount_condition = chromeos::disks::MOUNT_CONDITION_NONE; 180 volume_info.is_parent = true; 181 volume_info.is_read_only = true; 182 volume_info.volume_id = GenerateVolumeId(volume_info); 183 return volume_info; 184} 185 186} // namespace 187 188VolumeInfo::VolumeInfo() { 189} 190 191VolumeInfo::~VolumeInfo() { 192} 193 194VolumeManager::VolumeManager( 195 Profile* profile, 196 drive::DriveIntegrationService* drive_integration_service, 197 chromeos::PowerManagerClient* power_manager_client, 198 chromeos::disks::DiskMountManager* disk_mount_manager) 199 : profile_(profile), 200 drive_integration_service_(drive_integration_service), 201 disk_mount_manager_(disk_mount_manager), 202 mounted_disk_monitor_( 203 new MountedDiskMonitor(power_manager_client, disk_mount_manager)) { 204 DCHECK(disk_mount_manager); 205} 206 207VolumeManager::~VolumeManager() { 208} 209 210VolumeManager* VolumeManager::Get(content::BrowserContext* context) { 211 return VolumeManagerFactory::Get(context); 212} 213 214void VolumeManager::Initialize() { 215 const bool kNotRemounting = false; 216 217 // Path to mount user folders have changed several times. We need to migrate 218 // the old preferences on paths to the new format when needed. For the detail, 219 // see the comments in file_manager::util::MigratePathFromOldFormat, 220 // Note: Preferences related to downloads are handled in download_prefs.cc. 221 // TODO(kinaba): Remove this after several rounds of releases. 222 const base::FilePath old_path = 223 profile_->GetPrefs()->GetFilePath(prefs::kSelectFileLastDirectory); 224 base::FilePath new_path; 225 if (!old_path.empty() && 226 file_manager::util::MigratePathFromOldFormat(profile_, 227 old_path, &new_path)) { 228 profile_->GetPrefs()->SetFilePath(prefs::kSelectFileLastDirectory, 229 new_path); 230 } 231 232 // Register 'Downloads' folder for the profile to the file system. 233 if (!chromeos::ProfileHelper::IsSigninProfile(profile_)) { 234 const base::FilePath downloads = 235 file_manager::util::GetDownloadsFolderForProfile(profile_); 236 const bool success = RegisterDownloadsMountPoint(profile_, downloads); 237 DCHECK(success); 238 239 DoMountEvent(chromeos::MOUNT_ERROR_NONE, 240 CreateDownloadsVolumeInfo(downloads), 241 kNotRemounting); 242 } 243 244 // Subscribe to DriveIntegrationService. 245 if (drive_integration_service_) { 246 drive_integration_service_->AddObserver(this); 247 if (drive_integration_service_->IsMounted()) { 248 DoMountEvent(chromeos::MOUNT_ERROR_NONE, 249 CreateDriveVolumeInfo(profile_), 250 kNotRemounting); 251 } 252 } 253 254 // Subscribe to DiskMountManager. 255 disk_mount_manager_->AddObserver(this); 256 257 std::vector<VolumeInfo> archives; 258 259 const chromeos::disks::DiskMountManager::MountPointMap& mount_points = 260 disk_mount_manager_->mount_points(); 261 for (chromeos::disks::DiskMountManager::MountPointMap::const_iterator it = 262 mount_points.begin(); 263 it != mount_points.end(); 264 ++it) { 265 if (it->second.mount_type == chromeos::MOUNT_TYPE_ARCHIVE) { 266 // Archives are mounted after other type of volumes. See below. 267 archives.push_back(CreateVolumeInfoFromMountPointInfo(it->second, NULL)); 268 continue; 269 } 270 DoMountEvent( 271 chromeos::MOUNT_ERROR_NONE, 272 CreateVolumeInfoFromMountPointInfo( 273 it->second, 274 disk_mount_manager_->FindDiskBySourcePath(it->second.source_path)), 275 kNotRemounting); 276 } 277 278 // We mount archives only if they are opened from currently mounted volumes. 279 // To check the condition correctly in DoMountEvent, we care the order. 280 std::vector<bool> done(archives.size(), false); 281 for (size_t i = 0; i < archives.size(); ++i) { 282 if (!done[i]) { 283 std::vector<VolumeInfo> chain; 284 done[i] = true; 285 chain.push_back(archives[i]); 286 287 // If archives[i]'s source_path is in another archive, mount it first. 288 for (size_t parent = 0; parent < archives.size(); ++parent) { 289 if (!done[parent] && 290 archives[parent].mount_path.IsParent(chain.back().source_path)) { 291 done[parent] = true; 292 chain.push_back(archives[parent]); 293 parent = 0; // Search archives[parent]'s parent from the beginning. 294 } 295 } 296 297 // Mount from the tail of chain. 298 for (size_t i = chain.size(); i > 0; --i) 299 DoMountEvent(chromeos::MOUNT_ERROR_NONE, chain[i - 1], kNotRemounting); 300 } 301 } 302 303 disk_mount_manager_->RequestMountInfoRefresh(); 304 305 // Subscribe to Profile Preference change. 306 pref_change_registrar_.Init(profile_->GetPrefs()); 307 pref_change_registrar_.Add( 308 prefs::kExternalStorageDisabled, 309 base::Bind(&VolumeManager::OnExternalStorageDisabledChanged, 310 base::Unretained(this))); 311 312 if (CommandLine::ForCurrentProcess()->HasSwitch( 313 switches::kEnablePrivetStorage)) { 314 privet_volume_lister_.reset(new local_discovery::PrivetVolumeLister( 315 base::Bind(&VolumeManager::OnPrivetVolumesAvailable, 316 base::Unretained(this)))); 317 privet_volume_lister_->Start(); 318 } 319} 320 321void VolumeManager::Shutdown() { 322 pref_change_registrar_.RemoveAll(); 323 disk_mount_manager_->RemoveObserver(this); 324 325 if (drive_integration_service_) 326 drive_integration_service_->RemoveObserver(this); 327} 328 329void VolumeManager::AddObserver(VolumeManagerObserver* observer) { 330 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 331 DCHECK(observer); 332 observers_.AddObserver(observer); 333} 334 335void VolumeManager::RemoveObserver(VolumeManagerObserver* observer) { 336 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 337 DCHECK(observer); 338 observers_.RemoveObserver(observer); 339} 340 341std::vector<VolumeInfo> VolumeManager::GetVolumeInfoList() const { 342 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 343 344 std::vector<VolumeInfo> result; 345 for (std::map<std::string, VolumeInfo>::const_iterator iter = 346 mounted_volumes_.begin(); 347 iter != mounted_volumes_.end(); 348 ++iter) { 349 result.push_back(iter->second); 350 } 351 return result; 352} 353 354bool VolumeManager::FindVolumeInfoById(const std::string& volume_id, 355 VolumeInfo* result) const { 356 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 357 DCHECK(result); 358 359 std::map<std::string, VolumeInfo>::const_iterator iter = 360 mounted_volumes_.find(volume_id); 361 if (iter == mounted_volumes_.end()) 362 return false; 363 *result = iter->second; 364 return true; 365} 366 367bool VolumeManager::RegisterDownloadsDirectoryForTesting( 368 const base::FilePath& path) { 369 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 370 371 base::FilePath old_path; 372 if (FindDownloadsMountPointPath(profile_, &old_path)) { 373 DoUnmountEvent(chromeos::MOUNT_ERROR_NONE, 374 CreateDownloadsVolumeInfo(old_path)); 375 } 376 377 bool success = RegisterDownloadsMountPoint(profile_, path); 378 DoMountEvent( 379 success ? chromeos::MOUNT_ERROR_NONE : chromeos::MOUNT_ERROR_INVALID_PATH, 380 CreateDownloadsVolumeInfo(path), 381 false /* is_remounting */); 382 return success; 383} 384 385void VolumeManager::OnFileSystemMounted() { 386 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 387 388 // Raise mount event. 389 // We can pass chromeos::MOUNT_ERROR_NONE even when authentication is failed 390 // or network is unreachable. These two errors will be handled later. 391 VolumeInfo volume_info = CreateDriveVolumeInfo(profile_); 392 DoMountEvent(chromeos::MOUNT_ERROR_NONE, volume_info, 393 false /* is_remounting */); 394} 395 396void VolumeManager::OnFileSystemBeingUnmounted() { 397 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 398 399 VolumeInfo volume_info = CreateDriveVolumeInfo(profile_); 400 DoUnmountEvent(chromeos::MOUNT_ERROR_NONE, volume_info); 401} 402 403void VolumeManager::OnDiskEvent( 404 chromeos::disks::DiskMountManager::DiskEvent event, 405 const chromeos::disks::DiskMountManager::Disk* disk) { 406 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 407 408 // Disregard hidden devices. 409 if (disk->is_hidden()) 410 return; 411 412 switch (event) { 413 case chromeos::disks::DiskMountManager::DISK_ADDED: { 414 if (disk->device_path().empty()) { 415 DVLOG(1) << "Empty system path for " << disk->device_path(); 416 return; 417 } 418 419 bool mounting = false; 420 if (disk->mount_path().empty() && disk->has_media() && 421 !profile_->GetPrefs()->GetBoolean(prefs::kExternalStorageDisabled)) { 422 // If disk is not mounted yet and it has media and there is no policy 423 // forbidding external storage, give it a try. 424 // Initiate disk mount operation. MountPath auto-detects the filesystem 425 // format if the second argument is empty. The third argument (mount 426 // label) is not used in a disk mount operation. 427 disk_mount_manager_->MountPath( 428 disk->device_path(), std::string(), std::string(), 429 chromeos::MOUNT_TYPE_DEVICE); 430 mounting = true; 431 } 432 433 // Notify to observers. 434 FOR_EACH_OBSERVER(VolumeManagerObserver, observers_, 435 OnDiskAdded(*disk, mounting)); 436 return; 437 } 438 439 case chromeos::disks::DiskMountManager::DISK_REMOVED: 440 // If the disk is already mounted, unmount it. 441 if (!disk->mount_path().empty()) { 442 disk_mount_manager_->UnmountPath( 443 disk->mount_path(), 444 chromeos::UNMOUNT_OPTIONS_LAZY, 445 chromeos::disks::DiskMountManager::UnmountPathCallback()); 446 } 447 448 // Notify to observers. 449 FOR_EACH_OBSERVER(VolumeManagerObserver, observers_, 450 OnDiskRemoved(*disk)); 451 return; 452 453 case chromeos::disks::DiskMountManager::DISK_CHANGED: 454 DVLOG(1) << "Ignore CHANGED event."; 455 return; 456 } 457 NOTREACHED(); 458} 459 460void VolumeManager::OnDeviceEvent( 461 chromeos::disks::DiskMountManager::DeviceEvent event, 462 const std::string& device_path) { 463 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 464 DVLOG(1) << "OnDeviceEvent: " << event << ", " << device_path; 465 466 switch (event) { 467 case chromeos::disks::DiskMountManager::DEVICE_ADDED: 468 FOR_EACH_OBSERVER(VolumeManagerObserver, observers_, 469 OnDeviceAdded(device_path)); 470 return; 471 case chromeos::disks::DiskMountManager::DEVICE_REMOVED: 472 FOR_EACH_OBSERVER(VolumeManagerObserver, observers_, 473 OnDeviceRemoved(device_path)); 474 return; 475 case chromeos::disks::DiskMountManager::DEVICE_SCANNED: 476 DVLOG(1) << "Ignore SCANNED event: " << device_path; 477 return; 478 } 479 NOTREACHED(); 480} 481 482void VolumeManager::OnMountEvent( 483 chromeos::disks::DiskMountManager::MountEvent event, 484 chromeos::MountError error_code, 485 const chromeos::disks::DiskMountManager::MountPointInfo& mount_info) { 486 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 487 DCHECK_NE(chromeos::MOUNT_TYPE_INVALID, mount_info.mount_type); 488 489 if (mount_info.mount_type == chromeos::MOUNT_TYPE_ARCHIVE) { 490 // If the file is not mounted now, tell it to drive file system so that 491 // it can handle file caching correctly. 492 // Note that drive file system knows if the file is managed by drive file 493 // system or not, so here we report all paths. 494 if ((event == chromeos::disks::DiskMountManager::MOUNTING && 495 error_code != chromeos::MOUNT_ERROR_NONE) || 496 (event == chromeos::disks::DiskMountManager::UNMOUNTING && 497 error_code == chromeos::MOUNT_ERROR_NONE)) { 498 drive::FileSystemInterface* file_system = 499 drive::util::GetFileSystemByProfile(profile_); 500 if (file_system) { 501 file_system->MarkCacheFileAsUnmounted( 502 base::FilePath(mount_info.source_path), 503 base::Bind(&OnMarkCacheFileAsUnmounted)); 504 } 505 } 506 } 507 508 // Notify a mounting/unmounting event to observers. 509 const chromeos::disks::DiskMountManager::Disk* disk = 510 disk_mount_manager_->FindDiskBySourcePath(mount_info.source_path); 511 VolumeInfo volume_info = 512 CreateVolumeInfoFromMountPointInfo(mount_info, disk); 513 switch (event) { 514 case chromeos::disks::DiskMountManager::MOUNTING: { 515 bool is_remounting = 516 disk && mounted_disk_monitor_->DiskIsRemounting(*disk); 517 DoMountEvent(error_code, volume_info, is_remounting); 518 return; 519 } 520 case chromeos::disks::DiskMountManager::UNMOUNTING: 521 DoUnmountEvent(error_code, volume_info); 522 return; 523 } 524 NOTREACHED(); 525} 526 527void VolumeManager::OnFormatEvent( 528 chromeos::disks::DiskMountManager::FormatEvent event, 529 chromeos::FormatError error_code, 530 const std::string& device_path) { 531 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 532 DVLOG(1) << "OnDeviceEvent: " << event << ", " << error_code 533 << ", " << device_path; 534 535 switch (event) { 536 case chromeos::disks::DiskMountManager::FORMAT_STARTED: 537 FOR_EACH_OBSERVER( 538 VolumeManagerObserver, observers_, 539 OnFormatStarted(device_path, 540 error_code == chromeos::FORMAT_ERROR_NONE)); 541 return; 542 case chromeos::disks::DiskMountManager::FORMAT_COMPLETED: 543 if (error_code == chromeos::FORMAT_ERROR_NONE) { 544 // If format is completed successfully, try to mount the device. 545 // MountPath auto-detects filesystem format if second argument is 546 // empty. The third argument (mount label) is not used in a disk mount 547 // operation. 548 disk_mount_manager_->MountPath( 549 device_path, std::string(), std::string(), 550 chromeos::MOUNT_TYPE_DEVICE); 551 } 552 553 FOR_EACH_OBSERVER( 554 VolumeManagerObserver, observers_, 555 OnFormatCompleted(device_path, 556 error_code == chromeos::FORMAT_ERROR_NONE)); 557 558 return; 559 } 560 NOTREACHED(); 561} 562 563void VolumeManager::OnExternalStorageDisabledChanged() { 564 // If the policy just got disabled we have to unmount every device currently 565 // mounted. The opposite is fine - we can let the user re-plug her device to 566 // make it available. 567 if (profile_->GetPrefs()->GetBoolean(prefs::kExternalStorageDisabled)) { 568 // We do not iterate on mount_points directly, because mount_points can 569 // be changed by UnmountPath(). 570 // TODO(hidehiko): Is it necessary to unmount mounted archives, too, here? 571 while (!disk_mount_manager_->mount_points().empty()) { 572 std::string mount_path = 573 disk_mount_manager_->mount_points().begin()->second.mount_path; 574 disk_mount_manager_->UnmountPath( 575 mount_path, 576 chromeos::UNMOUNT_OPTIONS_NONE, 577 chromeos::disks::DiskMountManager::UnmountPathCallback()); 578 } 579 } 580} 581 582void VolumeManager::OnPrivetVolumesAvailable( 583 const local_discovery::PrivetVolumeLister::VolumeList& volumes) { 584 for (local_discovery::PrivetVolumeLister::VolumeList::const_iterator i = 585 volumes.begin(); i != volumes.end(); i++) { 586 VolumeInfo volume_info = CreatePrivetVolumeInfo(*i); 587 DoMountEvent(chromeos::MOUNT_ERROR_NONE, volume_info, false); 588 } 589} 590 591void VolumeManager::DoMountEvent(chromeos::MountError error_code, 592 const VolumeInfo& volume_info, 593 bool is_remounting) { 594 // Archive files are mounted globally in system. We however don't want to show 595 // archives from profile-specific folders (Drive/Downloads) of other users in 596 // multi-profile session. To this end, we filter out archives not on the 597 // volumes already mounted on this VolumeManager instance. 598 if (volume_info.type == VOLUME_TYPE_MOUNTED_ARCHIVE_FILE) { 599 // Source may be in Drive cache folder under the current profile directory. 600 bool from_current_profile = 601 profile_->GetPath().IsParent(volume_info.source_path); 602 for (std::map<std::string, VolumeInfo>::const_iterator iter = 603 mounted_volumes_.begin(); 604 !from_current_profile && iter != mounted_volumes_.end(); 605 ++iter) { 606 if (iter->second.mount_path.IsParent(volume_info.source_path)) 607 from_current_profile = true; 608 } 609 if (!from_current_profile) 610 return; 611 } 612 613 if (error_code == chromeos::MOUNT_ERROR_NONE || volume_info.mount_condition) 614 mounted_volumes_[volume_info.volume_id] = volume_info; 615 616 FOR_EACH_OBSERVER(VolumeManagerObserver, 617 observers_, 618 OnVolumeMounted(error_code, volume_info, is_remounting)); 619} 620 621void VolumeManager::DoUnmountEvent(chromeos::MountError error_code, 622 const VolumeInfo& volume_info) { 623 if (mounted_volumes_.find(volume_info.volume_id) == mounted_volumes_.end()) 624 return; 625 if (error_code == chromeos::MOUNT_ERROR_NONE) 626 mounted_volumes_.erase(volume_info.volume_id); 627 628 FOR_EACH_OBSERVER(VolumeManagerObserver, 629 observers_, 630 OnVolumeUnmounted(error_code, volume_info)); 631} 632 633} // namespace file_manager 634