| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 // StorageMonitorLinux implementation. | 5 // StorageMonitorLinux implementation. |
| 6 | 6 |
| 7 #include "components/storage_monitor/storage_monitor_linux.h" | 7 #include "components/storage_monitor/storage_monitor_linux.h" |
| 8 | 8 |
| 9 #include <mntent.h> | 9 #include <mntent.h> |
| 10 #include <stdio.h> | 10 #include <stdio.h> |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 uint64 total_size_in_bytes = 0; | 112 uint64 total_size_in_bytes = 0; |
| 113 if (!base::StringToUint64(partition_size, &total_size_in_bytes)) | 113 if (!base::StringToUint64(partition_size, &total_size_in_bytes)) |
| 114 return 0; | 114 return 0; |
| 115 return (total_size_in_bytes <= kuint64max / 512) ? | 115 return (total_size_in_bytes <= kuint64max / 512) ? |
| 116 total_size_in_bytes * 512 : 0; | 116 total_size_in_bytes * 512 : 0; |
| 117 } | 117 } |
| 118 | 118 |
| 119 // Gets the device information using udev library. | 119 // Gets the device information using udev library. |
| 120 scoped_ptr<StorageInfo> GetDeviceInfo(const base::FilePath& device_path, | 120 scoped_ptr<StorageInfo> GetDeviceInfo(const base::FilePath& device_path, |
| 121 const base::FilePath& mount_point) { | 121 const base::FilePath& mount_point) { |
| 122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 122 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 123 DCHECK(!device_path.empty()); | 123 DCHECK(!device_path.empty()); |
| 124 | 124 |
| 125 scoped_ptr<StorageInfo> storage_info; | 125 scoped_ptr<StorageInfo> storage_info; |
| 126 | 126 |
| 127 ScopedGetDeviceInfoResultRecorder results_recorder; | 127 ScopedGetDeviceInfoResultRecorder results_recorder; |
| 128 | 128 |
| 129 device::ScopedUdevPtr udev_obj(device::udev_new()); | 129 device::ScopedUdevPtr udev_obj(device::udev_new()); |
| 130 if (!udev_obj.get()) | 130 if (!udev_obj.get()) |
| 131 return storage_info.Pass(); | 131 return storage_info.Pass(); |
| 132 | 132 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 191 volume_label, | 191 volume_label, |
| 192 vendor_name, | 192 vendor_name, |
| 193 model_name, | 193 model_name, |
| 194 GetDeviceStorageSize(device_path, device.get()))); | 194 GetDeviceStorageSize(device_path, device.get()))); |
| 195 return storage_info.Pass(); | 195 return storage_info.Pass(); |
| 196 } | 196 } |
| 197 | 197 |
| 198 MtabWatcherLinux* CreateMtabWatcherLinuxOnFileThread( | 198 MtabWatcherLinux* CreateMtabWatcherLinuxOnFileThread( |
| 199 const base::FilePath& mtab_path, | 199 const base::FilePath& mtab_path, |
| 200 base::WeakPtr<MtabWatcherLinux::Delegate> delegate) { | 200 base::WeakPtr<MtabWatcherLinux::Delegate> delegate) { |
| 201 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 201 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 202 // Owned by caller. | 202 // Owned by caller. |
| 203 return new MtabWatcherLinux(mtab_path, delegate); | 203 return new MtabWatcherLinux(mtab_path, delegate); |
| 204 } | 204 } |
| 205 | 205 |
| 206 StorageMonitor::EjectStatus EjectPathOnFileThread( | 206 StorageMonitor::EjectStatus EjectPathOnFileThread( |
| 207 const base::FilePath& path, | 207 const base::FilePath& path, |
| 208 const base::FilePath& device) { | 208 const base::FilePath& device) { |
| 209 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 209 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 210 | 210 |
| 211 // Note: Linux LSB says umount should exist in /bin. | 211 // Note: Linux LSB says umount should exist in /bin. |
| 212 static const char kUmountBinary[] = "/bin/umount"; | 212 static const char kUmountBinary[] = "/bin/umount"; |
| 213 std::vector<std::string> command; | 213 std::vector<std::string> command; |
| 214 command.push_back(kUmountBinary); | 214 command.push_back(kUmountBinary); |
| 215 command.push_back(path.value()); | 215 command.push_back(path.value()); |
| 216 | 216 |
| 217 base::LaunchOptions options; | 217 base::LaunchOptions options; |
| 218 base::Process process = base::LaunchProcess(command, options); | 218 base::Process process = base::LaunchProcess(command, options); |
| 219 if (!process.IsValid()) | 219 if (!process.IsValid()) |
| (...skipping 17 matching lines...) Expand all Loading... |
| 237 | 237 |
| 238 return StorageMonitor::EJECT_OK; | 238 return StorageMonitor::EJECT_OK; |
| 239 } | 239 } |
| 240 | 240 |
| 241 } // namespace | 241 } // namespace |
| 242 | 242 |
| 243 StorageMonitorLinux::StorageMonitorLinux(const base::FilePath& path) | 243 StorageMonitorLinux::StorageMonitorLinux(const base::FilePath& path) |
| 244 : mtab_path_(path), | 244 : mtab_path_(path), |
| 245 get_device_info_callback_(base::Bind(&GetDeviceInfo)), | 245 get_device_info_callback_(base::Bind(&GetDeviceInfo)), |
| 246 weak_ptr_factory_(this) { | 246 weak_ptr_factory_(this) { |
| 247 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 247 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 248 } | 248 } |
| 249 | 249 |
| 250 StorageMonitorLinux::~StorageMonitorLinux() { | 250 StorageMonitorLinux::~StorageMonitorLinux() { |
| 251 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 251 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 252 } | 252 } |
| 253 | 253 |
| 254 void StorageMonitorLinux::Init() { | 254 void StorageMonitorLinux::Init() { |
| 255 DCHECK(!mtab_path_.empty()); | 255 DCHECK(!mtab_path_.empty()); |
| 256 | 256 |
| 257 BrowserThread::PostTaskAndReplyWithResult( | 257 BrowserThread::PostTaskAndReplyWithResult( |
| 258 BrowserThread::FILE, FROM_HERE, | 258 BrowserThread::FILE, FROM_HERE, |
| 259 base::Bind(&CreateMtabWatcherLinuxOnFileThread, | 259 base::Bind(&CreateMtabWatcherLinuxOnFileThread, |
| 260 mtab_path_, | 260 mtab_path_, |
| 261 weak_ptr_factory_.GetWeakPtr()), | 261 weak_ptr_factory_.GetWeakPtr()), |
| 262 base::Bind(&StorageMonitorLinux::OnMtabWatcherCreated, | 262 base::Bind(&StorageMonitorLinux::OnMtabWatcherCreated, |
| 263 weak_ptr_factory_.GetWeakPtr())); | 263 weak_ptr_factory_.GetWeakPtr())); |
| 264 | 264 |
| 265 if (!media_transfer_protocol_manager_) { | 265 if (!media_transfer_protocol_manager_) { |
| 266 scoped_refptr<base::MessageLoopProxy> loop_proxy = | 266 scoped_refptr<base::MessageLoopProxy> loop_proxy = |
| 267 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE); | 267 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE); |
| 268 media_transfer_protocol_manager_.reset( | 268 media_transfer_protocol_manager_.reset( |
| 269 device::MediaTransferProtocolManager::Initialize(loop_proxy)); | 269 device::MediaTransferProtocolManager::Initialize(loop_proxy)); |
| 270 } | 270 } |
| 271 | 271 |
| 272 media_transfer_protocol_device_observer_.reset( | 272 media_transfer_protocol_device_observer_.reset( |
| 273 new MediaTransferProtocolDeviceObserverLinux( | 273 new MediaTransferProtocolDeviceObserverLinux( |
| 274 receiver(), media_transfer_protocol_manager_.get())); | 274 receiver(), media_transfer_protocol_manager_.get())); |
| 275 } | 275 } |
| 276 | 276 |
| 277 bool StorageMonitorLinux::GetStorageInfoForPath( | 277 bool StorageMonitorLinux::GetStorageInfoForPath( |
| 278 const base::FilePath& path, | 278 const base::FilePath& path, |
| 279 StorageInfo* device_info) const { | 279 StorageInfo* device_info) const { |
| 280 DCHECK(device_info); | 280 DCHECK(device_info); |
| 281 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 281 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 282 | 282 |
| 283 // TODO(thestig) |media_transfer_protocol_device_observer_| should always be | 283 // TODO(thestig) |media_transfer_protocol_device_observer_| should always be |
| 284 // valid. | 284 // valid. |
| 285 if (media_transfer_protocol_device_observer_ && | 285 if (media_transfer_protocol_device_observer_ && |
| 286 media_transfer_protocol_device_observer_->GetStorageInfoForPath( | 286 media_transfer_protocol_device_observer_->GetStorageInfoForPath( |
| 287 path, device_info)) { | 287 path, device_info)) { |
| 288 return true; | 288 return true; |
| 289 } | 289 } |
| 290 | 290 |
| 291 if (!path.IsAbsolute()) | 291 if (!path.IsAbsolute()) |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 | 352 |
| 353 receiver()->ProcessDetach(device_id); | 353 receiver()->ProcessDetach(device_id); |
| 354 | 354 |
| 355 BrowserThread::PostTaskAndReplyWithResult( | 355 BrowserThread::PostTaskAndReplyWithResult( |
| 356 BrowserThread::FILE, FROM_HERE, | 356 BrowserThread::FILE, FROM_HERE, |
| 357 base::Bind(&EjectPathOnFileThread, path, device), | 357 base::Bind(&EjectPathOnFileThread, path, device), |
| 358 callback); | 358 callback); |
| 359 } | 359 } |
| 360 | 360 |
| 361 void StorageMonitorLinux::OnMtabWatcherCreated(MtabWatcherLinux* watcher) { | 361 void StorageMonitorLinux::OnMtabWatcherCreated(MtabWatcherLinux* watcher) { |
| 362 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 362 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 363 mtab_watcher_.reset(watcher); | 363 mtab_watcher_.reset(watcher); |
| 364 } | 364 } |
| 365 | 365 |
| 366 void StorageMonitorLinux::UpdateMtab(const MountPointDeviceMap& new_mtab) { | 366 void StorageMonitorLinux::UpdateMtab(const MountPointDeviceMap& new_mtab) { |
| 367 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 367 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 368 | 368 |
| 369 // Check existing mtab entries for unaccounted mount points. | 369 // Check existing mtab entries for unaccounted mount points. |
| 370 // These mount points must have been removed in the new mtab. | 370 // These mount points must have been removed in the new mtab. |
| 371 std::list<base::FilePath> mount_points_to_erase; | 371 std::list<base::FilePath> mount_points_to_erase; |
| 372 std::list<base::FilePath> multiple_mounted_devices_needing_reattachment; | 372 std::list<base::FilePath> multiple_mounted_devices_needing_reattachment; |
| 373 for (MountMap::const_iterator old_iter = mount_info_map_.begin(); | 373 for (MountMap::const_iterator old_iter = mount_info_map_.begin(); |
| 374 old_iter != mount_info_map_.end(); ++old_iter) { | 374 old_iter != mount_info_map_.end(); ++old_iter) { |
| 375 const base::FilePath& mount_point = old_iter->first; | 375 const base::FilePath& mount_point = old_iter->first; |
| 376 const base::FilePath& mount_device = old_iter->second.mount_device; | 376 const base::FilePath& mount_device = old_iter->second.mount_device; |
| 377 MountPointDeviceMap::const_iterator new_iter = new_mtab.find(mount_point); | 377 MountPointDeviceMap::const_iterator new_iter = new_mtab.find(mount_point); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 BrowserThread::PostTaskAndReply( | 458 BrowserThread::PostTaskAndReply( |
| 459 BrowserThread::FILE, FROM_HERE, | 459 BrowserThread::FILE, FROM_HERE, |
| 460 base::Bind(&base::DoNothing), | 460 base::Bind(&base::DoNothing), |
| 461 base::Bind(&StorageMonitorLinux::MarkInitialized, | 461 base::Bind(&StorageMonitorLinux::MarkInitialized, |
| 462 weak_ptr_factory_.GetWeakPtr())); | 462 weak_ptr_factory_.GetWeakPtr())); |
| 463 } | 463 } |
| 464 } | 464 } |
| 465 | 465 |
| 466 bool StorageMonitorLinux::IsDeviceAlreadyMounted( | 466 bool StorageMonitorLinux::IsDeviceAlreadyMounted( |
| 467 const base::FilePath& mount_device) const { | 467 const base::FilePath& mount_device) const { |
| 468 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 468 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 469 return ContainsKey(mount_priority_map_, mount_device); | 469 return ContainsKey(mount_priority_map_, mount_device); |
| 470 } | 470 } |
| 471 | 471 |
| 472 void StorageMonitorLinux::HandleDeviceMountedMultipleTimes( | 472 void StorageMonitorLinux::HandleDeviceMountedMultipleTimes( |
| 473 const base::FilePath& mount_device, | 473 const base::FilePath& mount_device, |
| 474 const base::FilePath& mount_point) { | 474 const base::FilePath& mount_point) { |
| 475 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 475 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 476 | 476 |
| 477 MountPriorityMap::iterator priority = mount_priority_map_.find(mount_device); | 477 MountPriorityMap::iterator priority = mount_priority_map_.find(mount_device); |
| 478 DCHECK(priority != mount_priority_map_.end()); | 478 DCHECK(priority != mount_priority_map_.end()); |
| 479 const base::FilePath& other_mount_point = priority->second.begin()->first; | 479 const base::FilePath& other_mount_point = priority->second.begin()->first; |
| 480 priority->second[mount_point] = false; | 480 priority->second[mount_point] = false; |
| 481 mount_info_map_[mount_point] = | 481 mount_info_map_[mount_point] = |
| 482 mount_info_map_.find(other_mount_point)->second; | 482 mount_info_map_.find(other_mount_point)->second; |
| 483 } | 483 } |
| 484 | 484 |
| 485 void StorageMonitorLinux::AddNewMount(const base::FilePath& mount_device, | 485 void StorageMonitorLinux::AddNewMount(const base::FilePath& mount_device, |
| 486 scoped_ptr<StorageInfo> storage_info) { | 486 scoped_ptr<StorageInfo> storage_info) { |
| 487 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 487 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 488 | 488 |
| 489 if (!storage_info) | 489 if (!storage_info) |
| 490 return; | 490 return; |
| 491 | 491 |
| 492 DCHECK(!storage_info->device_id().empty()); | 492 DCHECK(!storage_info->device_id().empty()); |
| 493 | 493 |
| 494 bool removable = StorageInfo::IsRemovableDevice(storage_info->device_id()); | 494 bool removable = StorageInfo::IsRemovableDevice(storage_info->device_id()); |
| 495 const base::FilePath mount_point(storage_info->location()); | 495 const base::FilePath mount_point(storage_info->location()); |
| 496 | 496 |
| 497 MountPointInfo mount_point_info; | 497 MountPointInfo mount_point_info; |
| 498 mount_point_info.mount_device = mount_device; | 498 mount_point_info.mount_device = mount_device; |
| 499 mount_point_info.storage_info = *storage_info; | 499 mount_point_info.storage_info = *storage_info; |
| 500 mount_info_map_[mount_point] = mount_point_info; | 500 mount_info_map_[mount_point] = mount_point_info; |
| 501 mount_priority_map_[mount_device][mount_point] = removable; | 501 mount_priority_map_[mount_device][mount_point] = removable; |
| 502 receiver()->ProcessAttach(*storage_info); | 502 receiver()->ProcessAttach(*storage_info); |
| 503 } | 503 } |
| 504 | 504 |
| 505 StorageMonitor* StorageMonitor::CreateInternal() { | 505 StorageMonitor* StorageMonitor::CreateInternal() { |
| 506 const base::FilePath kDefaultMtabPath("/etc/mtab"); | 506 const base::FilePath kDefaultMtabPath("/etc/mtab"); |
| 507 return new StorageMonitorLinux(kDefaultMtabPath); | 507 return new StorageMonitorLinux(kDefaultMtabPath); |
| 508 } | 508 } |
| 509 | 509 |
| 510 } // namespace storage_monitor | 510 } // namespace storage_monitor |
| OLD | NEW |