| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 #include "chrome/browser/chromeos/cros/mount_library.h" | 5 #include "chrome/browser/chromeos/cros/mount_library.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 file_path_(file_path), | 66 file_path_(file_path), |
| 67 device_label_(device_label), | 67 device_label_(device_label), |
| 68 drive_label_(drive_label), | 68 drive_label_(drive_label), |
| 69 parent_path_(parent_path), | 69 parent_path_(parent_path), |
| 70 device_type_(device_type), | 70 device_type_(device_type), |
| 71 total_size_(total_size), | 71 total_size_(total_size), |
| 72 is_parent_(is_parent), | 72 is_parent_(is_parent), |
| 73 is_read_only_(is_read_only), | 73 is_read_only_(is_read_only), |
| 74 has_media_(has_media), | 74 has_media_(has_media), |
| 75 on_boot_device_(on_boot_device) { | 75 on_boot_device_(on_boot_device) { |
| 76 // Add trailing slash to mount path. | |
| 77 if (mount_path_.length() && mount_path_.at(mount_path_.length() -1) != '/') | |
| 78 mount_path_ = mount_path_.append("/"); | |
| 79 } | 76 } |
| 80 | 77 |
| 81 MountLibrary::Disk::~Disk() {} | 78 MountLibrary::Disk::~Disk() {} |
| 82 | 79 |
| 83 class MountLibraryImpl : public MountLibrary { | 80 class MountLibraryImpl : public MountLibrary { |
| 84 | 81 |
| 85 struct UnmountDeviceRecursiveCallbackData { | 82 struct UnmountDeviceRecursiveCallbackData { |
| 86 MountLibraryImpl* const object; | 83 MountLibraryImpl* const object; |
| 87 void* user_data; | 84 void* user_data; |
| 88 UnmountDeviceRecursiveCallbackType callback; | 85 UnmountDeviceRecursiveCallbackType callback; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 const MountPathOptions& options) OVERRIDE { | 123 const MountPathOptions& options) OVERRIDE { |
| 127 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 124 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 128 if (!CrosLibrary::Get()->EnsureLoaded()) { | 125 if (!CrosLibrary::Get()->EnsureLoaded()) { |
| 129 OnMountCompleted(MOUNT_ERROR_LIBRARY_NOT_LOADED, | 126 OnMountCompleted(MOUNT_ERROR_LIBRARY_NOT_LOADED, |
| 130 MountPointInfo(source_path, NULL, type)); | 127 MountPointInfo(source_path, NULL, type)); |
| 131 return; | 128 return; |
| 132 } | 129 } |
| 133 MountSourcePath(source_path, type, options, &MountCompletedHandler, this); | 130 MountSourcePath(source_path, type, options, &MountCompletedHandler, this); |
| 134 } | 131 } |
| 135 | 132 |
| 136 virtual void UnmountPath(const char* path) OVERRIDE { | 133 virtual void UnmountPath(const char* mount_path) OVERRIDE { |
| 137 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 134 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 138 if (!CrosLibrary::Get()->EnsureLoaded()) { | 135 if (!CrosLibrary::Get()->EnsureLoaded()) { |
| 139 OnUnmountPath(path, | 136 OnUnmountPath(mount_path, |
| 140 MOUNT_METHOD_ERROR_LOCAL, | 137 MOUNT_METHOD_ERROR_LOCAL, |
| 141 kLibraryNotLoaded); | 138 kLibraryNotLoaded); |
| 142 return; | 139 return; |
| 143 } | 140 } |
| 144 UnmountMountPoint(path, &MountLibraryImpl::UnmountMountPointCallback, this); | 141 |
| 142 UnmountMountPoint(mount_path, &MountLibraryImpl::UnmountMountPointCallback, |
| 143 this); |
| 145 } | 144 } |
| 146 | 145 |
| 147 virtual void UnmountDeviceRecursive(const char* device_path, | 146 virtual void UnmountDeviceRecursive(const char* device_path, |
| 148 UnmountDeviceRecursiveCallbackType callback, void* user_data) | 147 UnmountDeviceRecursiveCallbackType callback, void* user_data) |
| 149 OVERRIDE { | 148 OVERRIDE { |
| 150 bool success = true; | 149 bool success = true; |
| 151 const char* error_message = NULL; | 150 const char* error_message = NULL; |
| 152 std::vector<const char*> devices_to_unmount; | 151 std::vector<const char*> devices_to_unmount; |
| 153 | 152 |
| 154 if (!CrosLibrary::Get()->EnsureLoaded()) { | 153 if (!CrosLibrary::Get()->EnsureLoaded()) { |
| 155 success = false; | 154 success = false; |
| 156 error_message = kLibraryNotLoaded; | 155 error_message = kLibraryNotLoaded; |
| 157 } else { | 156 } else { |
| 158 // Get list of all devices to unmount. | 157 // Get list of all devices to unmount. |
| 159 int device_path_len = strlen(device_path); | 158 int device_path_len = strlen(device_path); |
| 160 for (DiskMap::iterator it = disks_.begin(); it != disks_.end(); ++it) { | 159 for (DiskMap::iterator it = disks_.begin(); it != disks_.end(); ++it) { |
| 161 if (strncmp(device_path, it->second->device_path().c_str(), | 160 if (!it->second->mount_path().empty() && |
| 162 device_path_len) == 0) { | 161 strncmp(device_path, it->second->device_path().c_str(), |
| 163 devices_to_unmount.push_back(it->second->device_path().c_str()); | 162 device_path_len) == 0) { |
| 163 devices_to_unmount.push_back(it->second->mount_path().c_str()); |
| 164 } | 164 } |
| 165 } | 165 } |
| 166 | 166 |
| 167 // We should detect at least original device. | 167 // We should detect at least original device. |
| 168 if (devices_to_unmount.size() == 0) { | 168 if (devices_to_unmount.size() == 0) { |
| 169 success = false; | 169 if (disks_.find(device_path) == disks_.end()) { |
| 170 error_message = kDeviceNotFound; | 170 success = false; |
| 171 error_message = kDeviceNotFound; |
| 172 } else { |
| 173 // Nothing to unmount. |
| 174 callback(user_data, true); |
| 175 return; |
| 176 } |
| 171 } | 177 } |
| 172 } | 178 } |
| 173 | 179 |
| 174 if (success) { | 180 if (success) { |
| 175 // We will send the same callback data object to all Unmount calls and use | 181 // We will send the same callback data object to all Unmount calls and use |
| 176 // it to syncronize callbacks. | 182 // it to syncronize callbacks. |
| 177 UnmountDeviceRecursiveCallbackData* | 183 UnmountDeviceRecursiveCallbackData* |
| 178 cb_data = new UnmountDeviceRecursiveCallbackData(this, user_data, | 184 cb_data = new UnmountDeviceRecursiveCallbackData(this, user_data, |
| 179 callback, devices_to_unmount.size()); | 185 callback, devices_to_unmount.size()); |
| 180 for (std::vector<const char*>::iterator it = devices_to_unmount.begin(); | 186 for (std::vector<const char*>::iterator it = devices_to_unmount.begin(); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 MountType type, | 222 MountType type, |
| 217 const char* mount_path) { | 223 const char* mount_path) { |
| 218 DCHECK(object); | 224 DCHECK(object); |
| 219 MountLibraryImpl* self = static_cast<MountLibraryImpl*>(object); | 225 MountLibraryImpl* self = static_cast<MountLibraryImpl*>(object); |
| 220 self->OnMountCompleted(static_cast<MountError>(error_code), | 226 self->OnMountCompleted(static_cast<MountError>(error_code), |
| 221 MountPointInfo(source_path, mount_path, type)); | 227 MountPointInfo(source_path, mount_path, type)); |
| 222 } | 228 } |
| 223 | 229 |
| 224 // Callback for UnmountRemovableDevice method. | 230 // Callback for UnmountRemovableDevice method. |
| 225 static void UnmountMountPointCallback(void* object, | 231 static void UnmountMountPointCallback(void* object, |
| 226 const char* device_path, | 232 const char* mount_path, |
| 227 MountMethodErrorType error, | 233 MountMethodErrorType error, |
| 228 const char* error_message) { | 234 const char* error_message) { |
| 229 DCHECK(object); | 235 DCHECK(object); |
| 230 MountLibraryImpl* self = static_cast<MountLibraryImpl*>(object); | 236 MountLibraryImpl* self = static_cast<MountLibraryImpl*>(object); |
| 231 self->OnUnmountPath(device_path, error, error_message); | 237 self->OnUnmountPath(mount_path, error, error_message); |
| 232 } | 238 } |
| 233 | 239 |
| 234 // Callback for UnmountDeviceRecursive. | 240 // Callback for UnmountDeviceRecursive. |
| 235 static void UnmountDeviceRecursiveCallback(void* object, | 241 static void UnmountDeviceRecursiveCallback(void* object, |
| 236 const char* device_path, | 242 const char* mount_path, |
| 237 MountMethodErrorType error, | 243 MountMethodErrorType error, |
| 238 const char* error_message) { | 244 const char* error_message) { |
| 239 DCHECK(object); | 245 DCHECK(object); |
| 240 UnmountDeviceRecursiveCallbackData* cb_data = | 246 UnmountDeviceRecursiveCallbackData* cb_data = |
| 241 static_cast<UnmountDeviceRecursiveCallbackData*>(object); | 247 static_cast<UnmountDeviceRecursiveCallbackData*>(object); |
| 242 | 248 |
| 243 // Do standard processing for Unmount event. | 249 // Do standard processing for Unmount event. |
| 244 cb_data->object->OnUnmountPath(device_path, | 250 cb_data->object->OnUnmountPath(mount_path, |
| 245 error, | 251 error, |
| 246 error_message); | 252 error_message); |
| 247 if (error == MOUNT_METHOD_ERROR_LOCAL) { | 253 if (error == MOUNT_METHOD_ERROR_LOCAL) { |
| 248 cb_data->success = false; | 254 cb_data->success = false; |
| 249 } else if (error == MOUNT_METHOD_ERROR_NONE) { | 255 } else if (error == MOUNT_METHOD_ERROR_NONE) { |
| 250 LOG(WARNING) << device_path << " unmounted."; | 256 LOG(INFO) << mount_path << " unmounted."; |
| 251 } | 257 } |
| 252 | 258 |
| 253 // This is safe as long as all callbacks are called on the same thread as | 259 // This is safe as long as all callbacks are called on the same thread as |
| 254 // UnmountDeviceRecursive. | 260 // UnmountDeviceRecursive. |
| 255 cb_data->pending_callbacks_count--; | 261 cb_data->pending_callbacks_count--; |
| 256 | 262 |
| 257 if (cb_data->pending_callbacks_count == 0) { | 263 if (cb_data->pending_callbacks_count == 0) { |
| 258 cb_data->callback(cb_data->user_data, cb_data->success); | 264 cb_data->callback(cb_data->user_data, cb_data->success); |
| 259 delete cb_data; | 265 delete cb_data; |
| 260 } | 266 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 DCHECK(object); | 301 DCHECK(object); |
| 296 MountLibraryImpl* self = static_cast<MountLibraryImpl*>(object); | 302 MountLibraryImpl* self = static_cast<MountLibraryImpl*>(object); |
| 297 self->OnMountEvent(evt, device_path); | 303 self->OnMountEvent(evt, device_path); |
| 298 } | 304 } |
| 299 | 305 |
| 300 | 306 |
| 301 void OnMountCompleted(MountError error_code, | 307 void OnMountCompleted(MountError error_code, |
| 302 const MountPointInfo& mount_info) { | 308 const MountPointInfo& mount_info) { |
| 303 DCHECK(!mount_info.source_path.empty()); | 309 DCHECK(!mount_info.source_path.empty()); |
| 304 | 310 |
| 305 FireMountCompleted(MOUNTING, | 311 FireMountCompleted(MOUNTING, error_code, mount_info); |
| 306 error_code, | |
| 307 mount_info); | |
| 308 | 312 |
| 309 if (error_code == MOUNT_ERROR_NONE && | 313 if (error_code == MOUNT_ERROR_NONE && |
| 310 mount_points_.find(mount_info.source_path) == mount_points_.end()) { | 314 mount_points_.find(mount_info.mount_path) == mount_points_.end()) { |
| 311 mount_points_.insert(MountPointMap::value_type( | 315 mount_points_.insert(MountPointMap::value_type( |
| 312 mount_info.source_path.c_str(), | 316 mount_info.mount_path.c_str(), |
| 313 mount_info)); | 317 mount_info)); |
| 314 } | 318 } |
| 315 | 319 |
| 316 if (error_code == MOUNT_ERROR_NONE && | 320 if (error_code == MOUNT_ERROR_NONE && |
| 317 mount_info.mount_type == MOUNT_TYPE_DEVICE && | 321 mount_info.mount_type == MOUNT_TYPE_DEVICE && |
| 318 !mount_info.source_path.empty() && | 322 !mount_info.source_path.empty() && |
| 319 !mount_info.mount_path.empty()) { | 323 !mount_info.mount_path.empty()) { |
| 320 std::string path(mount_info.source_path); | 324 std::string path(mount_info.source_path); |
| 321 DiskMap::iterator iter = disks_.find(path); | 325 DiskMap::iterator iter = disks_.find(path); |
| 322 if (iter == disks_.end()) { | 326 if (iter == disks_.end()) { |
| 323 // disk might have been removed by now? | 327 // disk might have been removed by now? |
| 324 return; | 328 return; |
| 325 } | 329 } |
| 326 Disk* disk = iter->second; | 330 Disk* disk = iter->second; |
| 327 DCHECK(disk); | 331 DCHECK(disk); |
| 328 disk->set_mount_path(mount_info.mount_path.c_str()); | 332 disk->set_mount_path(mount_info.mount_path.c_str()); |
| 329 FireDiskStatusUpdate(MOUNT_DISK_MOUNTED, disk); | 333 FireDiskStatusUpdate(MOUNT_DISK_MOUNTED, disk); |
| 330 } | 334 } |
| 331 } | 335 } |
| 332 | 336 |
| 333 void OnUnmountPath(const char* source_path, | 337 void OnUnmountPath(const char* mount_path, |
| 334 MountMethodErrorType error, | 338 MountMethodErrorType error, |
| 335 const char* error_message) { | 339 const char* error_message) { |
| 336 DCHECK(source_path); | 340 DCHECK(mount_path); |
| 337 | 341 if (error == MOUNT_METHOD_ERROR_NONE && mount_path) { |
| 338 if (error == MOUNT_METHOD_ERROR_NONE && source_path) { | 342 MountPointMap::iterator mount_points_it = mount_points_.find(mount_path); |
| 339 MountPointMap::iterator mount_points_it = mount_points_.find(source_path); | |
| 340 if (mount_points_it == mount_points_.end()) | 343 if (mount_points_it == mount_points_.end()) |
| 341 return; | 344 return; |
| 342 // TODO(tbarzic): Add separate, PathUnmounted event to Observer. | 345 // TODO(tbarzic): Add separate, PathUnmounted event to Observer. |
| 343 FireMountCompleted( | 346 FireMountCompleted( |
| 344 UNMOUNTING, | 347 UNMOUNTING, |
| 345 MOUNT_ERROR_NONE, | 348 MOUNT_ERROR_NONE, |
| 346 MountPointInfo(mount_points_it->second.source_path.c_str(), | 349 MountPointInfo(mount_points_it->second.source_path.c_str(), |
| 347 mount_points_it->second.mount_path.c_str(), | 350 mount_points_it->second.mount_path.c_str(), |
| 348 mount_points_it->second.mount_type)); | 351 mount_points_it->second.mount_type)); |
| 352 std::string path(mount_points_it->second.source_path); |
| 349 mount_points_.erase(mount_points_it); | 353 mount_points_.erase(mount_points_it); |
| 350 | 354 |
| 351 std::string path(source_path); | |
| 352 DiskMap::iterator iter = disks_.find(path); | 355 DiskMap::iterator iter = disks_.find(path); |
| 353 if (iter == disks_.end()) { | 356 if (iter == disks_.end()) { |
| 354 // disk might have been removed by now? | 357 // disk might have been removed by now? |
| 355 return; | 358 return; |
| 356 } | 359 } |
| 357 Disk* disk = iter->second; | 360 Disk* disk = iter->second; |
| 358 DCHECK(disk); | 361 DCHECK(disk); |
| 359 disk->clear_mount_path(); | 362 disk->clear_mount_path(); |
| 360 FireDiskStatusUpdate(MOUNT_DISK_UNMOUNTED, disk); | 363 FireDiskStatusUpdate(MOUNT_DISK_UNMOUNTED, disk); |
| 361 } else { | 364 } else { |
| 362 LOG(WARNING) << "Unmount request failed for device " | 365 LOG(WARNING) << "Unmount request failed for device " |
| 363 << source_path << ", with error: " | 366 << mount_path << ", with error: " |
| 364 << (error_message ? error_message : "Unknown"); | 367 << (error_message ? error_message : "Unknown"); |
| 365 } | 368 } |
| 366 } | 369 } |
| 367 | 370 |
| 368 void OnGetDiskProperties(const char* device_path, | 371 void OnGetDiskProperties(const char* device_path, |
| 369 const DiskInfo* disk1, | 372 const DiskInfo* disk1, |
| 370 MountMethodErrorType error, | 373 MountMethodErrorType error, |
| 371 const char* error_message) { | 374 const char* error_message) { |
| 372 DCHECK(device_path); | 375 DCHECK(device_path); |
| 373 if (error == MOUNT_METHOD_ERROR_NONE && device_path) { | 376 if (error == MOUNT_METHOD_ERROR_NONE && device_path) { |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 583 // MountLibrary overrides. | 586 // MountLibrary overrides. |
| 584 virtual void AddObserver(Observer* observer) OVERRIDE {} | 587 virtual void AddObserver(Observer* observer) OVERRIDE {} |
| 585 virtual void RemoveObserver(Observer* observer) OVERRIDE {} | 588 virtual void RemoveObserver(Observer* observer) OVERRIDE {} |
| 586 virtual const DiskMap& disks() const OVERRIDE { return disks_; } | 589 virtual const DiskMap& disks() const OVERRIDE { return disks_; } |
| 587 virtual const MountPointMap& mount_points() const OVERRIDE { | 590 virtual const MountPointMap& mount_points() const OVERRIDE { |
| 588 return mount_points_; | 591 return mount_points_; |
| 589 } | 592 } |
| 590 virtual void RequestMountInfoRefresh() OVERRIDE {} | 593 virtual void RequestMountInfoRefresh() OVERRIDE {} |
| 591 virtual void MountPath(const char* source_path, MountType type, | 594 virtual void MountPath(const char* source_path, MountType type, |
| 592 const MountPathOptions& options) OVERRIDE {} | 595 const MountPathOptions& options) OVERRIDE {} |
| 593 virtual void UnmountPath(const char* path) OVERRIDE {} | 596 virtual void UnmountPath(const char* mount_path) OVERRIDE {} |
| 594 virtual void UnmountDeviceRecursive(const char* device_path, | 597 virtual void UnmountDeviceRecursive(const char* device_path, |
| 595 UnmountDeviceRecursiveCallbackType callback, void* user_data) | 598 UnmountDeviceRecursiveCallbackType callback, void* user_data) |
| 596 OVERRIDE {} | 599 OVERRIDE {} |
| 597 | 600 |
| 598 private: | 601 private: |
| 599 // The list of disks found. | 602 // The list of disks found. |
| 600 DiskMap disks_; | 603 DiskMap disks_; |
| 601 MountPointMap mount_points_; | 604 MountPointMap mount_points_; |
| 602 | 605 |
| 603 DISALLOW_COPY_AND_ASSIGN(MountLibraryStubImpl); | 606 DISALLOW_COPY_AND_ASSIGN(MountLibraryStubImpl); |
| 604 }; | 607 }; |
| 605 | 608 |
| 606 // static | 609 // static |
| 607 MountLibrary* MountLibrary::GetImpl(bool stub) { | 610 MountLibrary* MountLibrary::GetImpl(bool stub) { |
| 608 if (stub) | 611 if (stub) |
| 609 return new MountLibraryStubImpl(); | 612 return new MountLibraryStubImpl(); |
| 610 else | 613 else |
| 611 return new MountLibraryImpl(); | 614 return new MountLibraryImpl(); |
| 612 } | 615 } |
| 613 | 616 |
| 614 } // namespace chromeos | 617 } // namespace chromeos |
| 615 | 618 |
| 616 // Allows InvokeLater without adding refcounting. This class is a Singleton and | 619 // Allows InvokeLater without adding refcounting. This class is a Singleton and |
| 617 // won't be deleted until it's last InvokeLater is run. | 620 // won't be deleted until it's last InvokeLater is run. |
| 618 DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::MountLibraryImpl); | 621 DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::MountLibraryImpl); |
| 619 | 622 |
| OLD | NEW |