| 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 #include "components/storage_monitor/volume_mount_watcher_win.h" | 5 #include "components/storage_monitor/volume_mount_watcher_win.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 #include <stdint.h> | 9 #include <stdint.h> |
| 10 | 10 |
| 11 #include <dbt.h> | 11 #include <dbt.h> |
| 12 #include <fileapi.h> | 12 #include <fileapi.h> |
| 13 #include <shlobj.h> | 13 #include <shlobj.h> |
| 14 #include <winioctl.h> | 14 #include <winioctl.h> |
| 15 | 15 |
| 16 #include <algorithm> | 16 #include <algorithm> |
| 17 | 17 |
| 18 #include "base/bind_helpers.h" | 18 #include "base/bind_helpers.h" |
| 19 #include "base/metrics/histogram_macros.h" | |
| 20 #include "base/stl_util.h" | 19 #include "base/stl_util.h" |
| 21 #include "base/strings/string_number_conversions.h" | 20 #include "base/strings/string_number_conversions.h" |
| 22 #include "base/strings/string_util.h" | 21 #include "base/strings/string_util.h" |
| 23 #include "base/strings/stringprintf.h" | 22 #include "base/strings/stringprintf.h" |
| 24 #include "base/strings/utf_string_conversions.h" | 23 #include "base/strings/utf_string_conversions.h" |
| 25 #include "base/sys_info.h" | 24 #include "base/sys_info.h" |
| 26 #include "base/task_runner_util.h" | 25 #include "base/task_runner_util.h" |
| 27 #include "base/threading/sequenced_worker_pool.h" | 26 #include "base/threading/sequenced_worker_pool.h" |
| 28 #include "base/time/time.h" | 27 #include "base/time/time.h" |
| 29 #include "base/win/scoped_handle.h" | 28 #include "base/win/scoped_handle.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 40 const DWORD kMaxPathBufLen = MAX_PATH + 1; | 39 const DWORD kMaxPathBufLen = MAX_PATH + 1; |
| 41 | 40 |
| 42 const char kDeviceInfoTaskRunnerName[] = "device-info-task-runner"; | 41 const char kDeviceInfoTaskRunnerName[] = "device-info-task-runner"; |
| 43 | 42 |
| 44 enum DeviceType { | 43 enum DeviceType { |
| 45 FLOPPY, | 44 FLOPPY, |
| 46 REMOVABLE, | 45 REMOVABLE, |
| 47 FIXED, | 46 FIXED, |
| 48 }; | 47 }; |
| 49 | 48 |
| 50 // Histogram values for recording frequencies of eject attempts and | |
| 51 // outcomes. | |
| 52 enum EjectWinLockOutcomes { | |
| 53 LOCK_ATTEMPT, | |
| 54 LOCK_TIMEOUT, | |
| 55 LOCK_TIMEOUT2, | |
| 56 NUM_LOCK_OUTCOMES, | |
| 57 }; | |
| 58 | |
| 59 // We are trying to figure out whether the drive is a fixed volume, | 49 // We are trying to figure out whether the drive is a fixed volume, |
| 60 // a removable storage, or a floppy. A "floppy" here means "a volume we | 50 // a removable storage, or a floppy. A "floppy" here means "a volume we |
| 61 // want to basically ignore because it won't fit media and will spin | 51 // want to basically ignore because it won't fit media and will spin |
| 62 // if we touch it to get volume metadata." GetDriveType returns DRIVE_REMOVABLE | 52 // if we touch it to get volume metadata." GetDriveType returns DRIVE_REMOVABLE |
| 63 // on either floppy or removable volumes. The DRIVE_CDROM type is handled | 53 // on either floppy or removable volumes. The DRIVE_CDROM type is handled |
| 64 // as a floppy, as are DRIVE_UNKNOWN and DRIVE_NO_ROOT_DIR, as there are | 54 // as a floppy, as are DRIVE_UNKNOWN and DRIVE_NO_ROOT_DIR, as there are |
| 65 // reports that some floppy drives don't report as DRIVE_REMOVABLE. | 55 // reports that some floppy drives don't report as DRIVE_REMOVABLE. |
| 66 DeviceType GetDeviceType(const base::string16& mount_point) { | 56 DeviceType GetDeviceType(const base::string16& mount_point) { |
| 67 UINT drive_type = GetDriveType(mount_point.c_str()); | 57 UINT drive_type = GetDriveType(mount_point.c_str()); |
| 68 if (drive_type == DRIVE_FIXED || drive_type == DRIVE_REMOTE || | 58 if (drive_type == DRIVE_FIXED || drive_type == DRIVE_REMOTE || |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 255 } | 245 } |
| 256 | 246 |
| 257 DWORD bytes_returned = 0; // Unused, but necessary for ioctl's. | 247 DWORD bytes_returned = 0; // Unused, but necessary for ioctl's. |
| 258 | 248 |
| 259 // Lock the drive to be ejected (so that other processes can't open | 249 // Lock the drive to be ejected (so that other processes can't open |
| 260 // files on it). If this fails, it means some other process has files | 250 // files on it). If this fails, it means some other process has files |
| 261 // open on the device. Note that the lock is released when the volume | 251 // open on the device. Note that the lock is released when the volume |
| 262 // handle is closed, and this is done by the ScopedHandle above. | 252 // handle is closed, and this is done by the ScopedHandle above. |
| 263 BOOL locked = DeviceIoControl(volume_handle.Get(), FSCTL_LOCK_VOLUME, | 253 BOOL locked = DeviceIoControl(volume_handle.Get(), FSCTL_LOCK_VOLUME, |
| 264 NULL, 0, NULL, 0, &bytes_returned, NULL); | 254 NULL, 0, NULL, 0, &bytes_returned, NULL); |
| 265 UMA_HISTOGRAM_ENUMERATION("StorageMonitor.EjectWinLock", | |
| 266 LOCK_ATTEMPT, NUM_LOCK_OUTCOMES); | |
| 267 if (!locked) { | 255 if (!locked) { |
| 268 UMA_HISTOGRAM_ENUMERATION("StorageMonitor.EjectWinLock", | |
| 269 iteration == 0 ? LOCK_TIMEOUT : LOCK_TIMEOUT2, | |
| 270 NUM_LOCK_OUTCOMES); | |
| 271 const int kNumLockRetries = 1; | 256 const int kNumLockRetries = 1; |
| 272 const base::TimeDelta kLockRetryInterval = | 257 const base::TimeDelta kLockRetryInterval = |
| 273 base::TimeDelta::FromMilliseconds(500); | 258 base::TimeDelta::FromMilliseconds(500); |
| 274 if (iteration < kNumLockRetries) { | 259 if (iteration < kNumLockRetries) { |
| 275 // Try again -- the lock may have been a transient one. This happens on | 260 // Try again -- the lock may have been a transient one. This happens on |
| 276 // things like AV disk lock for some reason, or another process | 261 // things like AV disk lock for some reason, or another process |
| 277 // transient disk lock. | 262 // transient disk lock. |
| 278 task_runner->PostDelayedTask( | 263 task_runner->PostDelayedTask( |
| 279 FROM_HERE, | 264 FROM_HERE, |
| 280 base::Bind(&EjectDeviceInThreadPool, | 265 base::Bind(&EjectDeviceInThreadPool, |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 547 callback.Run(StorageMonitor::EJECT_FAILURE); | 532 callback.Run(StorageMonitor::EJECT_FAILURE); |
| 548 return; | 533 return; |
| 549 } | 534 } |
| 550 | 535 |
| 551 device_info_task_runner_->PostTask( | 536 device_info_task_runner_->PostTask( |
| 552 FROM_HERE, base::Bind(&EjectDeviceInThreadPool, device, callback, | 537 FROM_HERE, base::Bind(&EjectDeviceInThreadPool, device, callback, |
| 553 device_info_task_runner_, 0)); | 538 device_info_task_runner_, 0)); |
| 554 } | 539 } |
| 555 | 540 |
| 556 } // namespace storage_monitor | 541 } // namespace storage_monitor |
| OLD | NEW |