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 // chrome::MediaStorageUtil implementation. | 5 // chrome::MediaStorageUtil implementation. |
6 | 6 |
7 #include "chrome/browser/system_monitor/media_storage_util.h" | 7 #include "chrome/browser/system_monitor/media_storage_util.h" |
8 | 8 |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/callback.h" | 11 #include "base/callback.h" |
12 #include "base/file_util.h" | 12 #include "base/file_util.h" |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
| 15 #include "base/stl_util.h" |
15 #include "base/system_monitor/system_monitor.h" | 16 #include "base/system_monitor/system_monitor.h" |
16 #include "base/utf_string_conversions.h" | 17 #include "base/utf_string_conversions.h" |
17 #include "chrome/browser/system_monitor/media_device_notifications_utils.h" | 18 #include "chrome/browser/system_monitor/media_device_notifications_utils.h" |
18 #include "content/public/browser/browser_thread.h" | 19 #include "content/public/browser/browser_thread.h" |
19 | 20 |
20 #if defined(OS_CHROMEOS) | 21 #if defined(OS_CHROMEOS) |
21 #include "chrome/browser/system_monitor/removable_device_notifications_chromeos.
h" | 22 #include "chrome/browser/system_monitor/removable_device_notifications_chromeos.
h" |
22 #elif defined(OS_LINUX) | 23 #elif defined(OS_LINUX) |
23 #include "chrome/browser/system_monitor/removable_device_notifications_linux.h" | 24 #include "chrome/browser/system_monitor/removable_device_notifications_linux.h" |
24 #elif defined(OS_MACOSX) | 25 #elif defined(OS_MACOSX) |
25 #include "chrome/browser/system_monitor/removable_device_notifications_mac.h" | 26 #include "chrome/browser/system_monitor/removable_device_notifications_mac.h" |
26 #elif defined(OS_WIN) | 27 #elif defined(OS_WIN) |
27 #include "chrome/browser/system_monitor/removable_device_notifications_window_wi
n.h" | 28 #include "chrome/browser/system_monitor/removable_device_notifications_window_wi
n.h" |
28 #endif | 29 #endif |
29 | 30 |
30 #if defined(OS_LINUX) // Implies OS_CHROMEOS | 31 #if defined(OS_LINUX) // Implies OS_CHROMEOS |
31 #include "chrome/browser/system_monitor/media_transfer_protocol_device_observer_
linux.h" | 32 #include "chrome/browser/system_monitor/media_transfer_protocol_device_observer_
linux.h" |
32 #endif | 33 #endif |
33 | 34 |
34 using base::SystemMonitor; | 35 using base::SystemMonitor; |
35 using content::BrowserThread; | 36 using content::BrowserThread; |
36 | 37 |
| 38 const char kRootPath[] = "/"; |
| 39 |
37 namespace chrome { | 40 namespace chrome { |
38 | 41 |
39 namespace { | 42 namespace { |
40 | 43 |
41 typedef std::vector<SystemMonitor::RemovableStorageInfo> RemovableStorageInfo; | |
42 | |
43 // MediaDeviceNotification.DeviceInfo histogram values. | 44 // MediaDeviceNotification.DeviceInfo histogram values. |
44 enum DeviceInfoHistogramBuckets { | 45 enum DeviceInfoHistogramBuckets { |
45 MASS_STORAGE_DEVICE_NAME_AND_UUID_AVAILABLE, | 46 MASS_STORAGE_DEVICE_NAME_AND_UUID_AVAILABLE, |
46 MASS_STORAGE_DEVICE_UUID_MISSING, | 47 MASS_STORAGE_DEVICE_UUID_MISSING, |
47 MASS_STORAGE_DEVICE_NAME_MISSING, | 48 MASS_STORAGE_DEVICE_NAME_MISSING, |
48 MASS_STORAGE_DEVICE_NAME_AND_UUID_MISSING, | 49 MASS_STORAGE_DEVICE_NAME_AND_UUID_MISSING, |
49 MTP_STORAGE_DEVICE_NAME_AND_UUID_AVAILABLE, | 50 MTP_STORAGE_DEVICE_NAME_AND_UUID_AVAILABLE, |
50 MTP_STORAGE_DEVICE_UUID_MISSING, | 51 MTP_STORAGE_DEVICE_UUID_MISSING, |
51 MTP_STORAGE_DEVICE_NAME_MISSING, | 52 MTP_STORAGE_DEVICE_NAME_MISSING, |
52 MTP_STORAGE_DEVICE_NAME_AND_UUID_MISSING, | 53 MTP_STORAGE_DEVICE_NAME_AND_UUID_MISSING, |
53 DEVICE_INFO_BUCKET_BOUNDARY | 54 DEVICE_INFO_BUCKET_BOUNDARY |
54 }; | 55 }; |
55 | 56 |
56 // Prefix constants for different device id spaces. | 57 // Prefix constants for different device id spaces. |
57 const char kRemovableMassStorageWithDCIMPrefix[] = "dcim:"; | 58 const char kRemovableMassStorageWithDCIMPrefix[] = "dcim:"; |
58 const char kRemovableMassStorageNoDCIMPrefix[] = "nodcim:"; | 59 const char kRemovableMassStorageNoDCIMPrefix[] = "nodcim:"; |
59 const char kFixedMassStoragePrefix[] = "path:"; | 60 const char kFixedMassStoragePrefix[] = "path:"; |
60 const char kMtpPtpPrefix[] = "mtp:"; | 61 const char kMtpPtpPrefix[] = "mtp:"; |
| 62 const char kMacImageCapture[] = "ic:"; |
61 | 63 |
62 static bool (*g_test_get_device_info_from_path_function)( // NOLINT | 64 static bool (*g_test_get_device_info_from_path_function)( // NOLINT |
63 const FilePath& path, std::string* device_id, string16* device_name, | 65 const FilePath& path, std::string* device_id, string16* device_name, |
64 FilePath* relative_path) = NULL; | 66 FilePath* relative_path) = NULL; |
65 | 67 |
66 void ValidatePathOnFileThread( | 68 void ValidatePathOnFileThread( |
67 const FilePath& path, const MediaStorageUtil::BoolCallback& callback) { | 69 const FilePath& path, const MediaStorageUtil::BoolCallback& callback) { |
68 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 70 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
69 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 71 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
70 base::Bind(callback, file_util::PathExists(path))); | 72 base::Bind(callback, file_util::PathExists(path))); |
71 } | 73 } |
72 | 74 |
| 75 bool IsRemovableStorageAttached(const std::string& id) { |
| 76 std::vector<SystemMonitor::RemovableStorageInfo> media_devices = |
| 77 SystemMonitor::Get()->GetAttachedRemovableStorage(); |
| 78 for (std::vector<SystemMonitor::RemovableStorageInfo>::const_iterator it = |
| 79 media_devices.begin(); |
| 80 it != media_devices.end(); |
| 81 ++it) { |
| 82 if (it->device_id == id) |
| 83 return true; |
| 84 } |
| 85 return false; |
| 86 } |
| 87 |
73 FilePath::StringType FindRemovableStorageLocationById( | 88 FilePath::StringType FindRemovableStorageLocationById( |
74 const std::string& device_id) { | 89 const std::string& device_id) { |
75 RemovableStorageInfo media_devices = | 90 std::vector<SystemMonitor::RemovableStorageInfo> media_devices = |
76 SystemMonitor::Get()->GetAttachedRemovableStorage(); | 91 SystemMonitor::Get()->GetAttachedRemovableStorage(); |
77 for (RemovableStorageInfo::const_iterator it = media_devices.begin(); | 92 for (std::vector<SystemMonitor::RemovableStorageInfo>::const_iterator it = |
| 93 media_devices.begin(); |
78 it != media_devices.end(); | 94 it != media_devices.end(); |
79 ++it) { | 95 ++it) { |
80 if (it->device_id == device_id) | 96 if (it->device_id == device_id) |
81 return it->location; | 97 return it->location; |
82 } | 98 } |
83 return FilePath::StringType(); | 99 return FilePath::StringType(); |
84 } | 100 } |
85 | 101 |
86 void FilterAttachedDevicesOnFileThread(MediaStorageUtil::DeviceIdSet* devices) { | 102 void FilterAttachedDevicesOnFileThread(MediaStorageUtil::DeviceIdSet* devices) { |
87 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 103 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
88 MediaStorageUtil::DeviceIdSet missing_devices; | 104 MediaStorageUtil::DeviceIdSet missing_devices; |
89 | 105 |
90 for (MediaStorageUtil::DeviceIdSet::const_iterator it = devices->begin(); | 106 for (MediaStorageUtil::DeviceIdSet::const_iterator it = devices->begin(); |
91 it != devices->end(); | 107 it != devices->end(); |
92 ++it) { | 108 ++it) { |
93 MediaStorageUtil::Type type; | 109 MediaStorageUtil::Type type; |
94 std::string unique_id; | 110 std::string unique_id; |
95 if (!MediaStorageUtil::CrackDeviceId(*it, &type, &unique_id)) { | 111 if (!MediaStorageUtil::CrackDeviceId(*it, &type, &unique_id)) { |
96 missing_devices.insert(*it); | 112 missing_devices.insert(*it); |
97 continue; | 113 continue; |
98 } | 114 } |
99 | 115 |
100 if (type == MediaStorageUtil::FIXED_MASS_STORAGE) { | 116 if (type == MediaStorageUtil::FIXED_MASS_STORAGE) { |
101 if (!file_util::PathExists(FilePath::FromUTF8Unsafe(unique_id))) | 117 if (!file_util::PathExists(FilePath::FromUTF8Unsafe(unique_id))) |
102 missing_devices.insert(*it); | 118 missing_devices.insert(*it); |
103 continue; | 119 continue; |
104 } | 120 } |
105 | 121 |
106 DCHECK(type == MediaStorageUtil::MTP_OR_PTP || | 122 if (!IsRemovableStorageAttached(*it)) |
107 type == MediaStorageUtil::REMOVABLE_MASS_STORAGE_WITH_DCIM || | |
108 type == MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM); | |
109 if (FindRemovableStorageLocationById(*it).empty()) | |
110 missing_devices.insert(*it); | 123 missing_devices.insert(*it); |
111 } | 124 } |
112 | 125 |
113 for (MediaStorageUtil::DeviceIdSet::const_iterator it = | 126 for (MediaStorageUtil::DeviceIdSet::const_iterator it = |
114 missing_devices.begin(); | 127 missing_devices.begin(); |
115 it != missing_devices.end(); | 128 it != missing_devices.end(); |
116 ++it) { | 129 ++it) { |
117 devices->erase(*it); | 130 devices->erase(*it); |
118 } | 131 } |
119 } | 132 } |
120 | 133 |
121 } // namespace | 134 } // namespace |
122 | 135 |
123 // static | 136 // static |
124 std::string MediaStorageUtil::MakeDeviceId(Type type, | 137 std::string MediaStorageUtil::MakeDeviceId(Type type, |
125 const std::string& unique_id) { | 138 const std::string& unique_id) { |
126 DCHECK(!unique_id.empty()); | 139 DCHECK(!unique_id.empty()); |
127 switch (type) { | 140 switch (type) { |
128 case REMOVABLE_MASS_STORAGE_WITH_DCIM: | 141 case REMOVABLE_MASS_STORAGE_WITH_DCIM: |
129 return std::string(kRemovableMassStorageWithDCIMPrefix) + unique_id; | 142 return std::string(kRemovableMassStorageWithDCIMPrefix) + unique_id; |
130 case REMOVABLE_MASS_STORAGE_NO_DCIM: | 143 case REMOVABLE_MASS_STORAGE_NO_DCIM: |
131 return std::string(kRemovableMassStorageNoDCIMPrefix) + unique_id; | 144 return std::string(kRemovableMassStorageNoDCIMPrefix) + unique_id; |
132 case FIXED_MASS_STORAGE: | 145 case FIXED_MASS_STORAGE: |
133 return std::string(kFixedMassStoragePrefix) + unique_id; | 146 return std::string(kFixedMassStoragePrefix) + unique_id; |
134 case MTP_OR_PTP: | 147 case MTP_OR_PTP: |
135 return std::string(kMtpPtpPrefix) + unique_id; | 148 return std::string(kMtpPtpPrefix) + unique_id; |
| 149 case MAC_IMAGE_CAPTURE: |
| 150 return std::string(kMacImageCapture) + unique_id; |
136 } | 151 } |
137 NOTREACHED(); | 152 NOTREACHED(); |
138 return std::string(); | 153 return std::string(); |
139 } | 154 } |
140 | 155 |
141 // static | 156 // static |
142 bool MediaStorageUtil::CrackDeviceId(const std::string& device_id, | 157 bool MediaStorageUtil::CrackDeviceId(const std::string& device_id, |
143 Type* type, std::string* unique_id) { | 158 Type* type, std::string* unique_id) { |
144 size_t prefix_length = device_id.find_first_of(':'); | 159 size_t prefix_length = device_id.find_first_of(':'); |
145 std::string prefix = prefix_length != std::string::npos ? | 160 std::string prefix = prefix_length != std::string::npos ? |
146 device_id.substr(0, prefix_length + 1) : ""; | 161 device_id.substr(0, prefix_length + 1) : ""; |
147 | 162 |
148 Type found_type; | 163 Type found_type; |
149 if (prefix == kRemovableMassStorageWithDCIMPrefix) { | 164 if (prefix == kRemovableMassStorageWithDCIMPrefix) { |
150 found_type = REMOVABLE_MASS_STORAGE_WITH_DCIM; | 165 found_type = REMOVABLE_MASS_STORAGE_WITH_DCIM; |
151 } else if (prefix == kRemovableMassStorageNoDCIMPrefix) { | 166 } else if (prefix == kRemovableMassStorageNoDCIMPrefix) { |
152 found_type = REMOVABLE_MASS_STORAGE_NO_DCIM; | 167 found_type = REMOVABLE_MASS_STORAGE_NO_DCIM; |
153 } else if (prefix == kFixedMassStoragePrefix) { | 168 } else if (prefix == kFixedMassStoragePrefix) { |
154 found_type = FIXED_MASS_STORAGE; | 169 found_type = FIXED_MASS_STORAGE; |
155 } else if (prefix == kMtpPtpPrefix) { | 170 } else if (prefix == kMtpPtpPrefix) { |
156 found_type = MTP_OR_PTP; | 171 found_type = MTP_OR_PTP; |
| 172 } else if (prefix == kMacImageCapture) { |
| 173 found_type = MAC_IMAGE_CAPTURE; |
157 } else { | 174 } else { |
158 NOTREACHED(); | 175 NOTREACHED(); |
159 return false; | 176 return false; |
160 } | 177 } |
161 if (type) | 178 if (type) |
162 *type = found_type; | 179 *type = found_type; |
163 | 180 |
164 if (unique_id) | 181 if (unique_id) |
165 *unique_id = device_id.substr(prefix_length + 1); | 182 *unique_id = device_id.substr(prefix_length + 1); |
166 return true; | 183 return true; |
167 } | 184 } |
168 | 185 |
169 // static | 186 // static |
170 bool MediaStorageUtil::IsMediaDevice(const std::string& device_id) { | 187 bool MediaStorageUtil::IsMediaDevice(const std::string& device_id) { |
171 Type type; | 188 Type type; |
172 return CrackDeviceId(device_id, &type, NULL) && | 189 return CrackDeviceId(device_id, &type, NULL) && |
173 (type == REMOVABLE_MASS_STORAGE_WITH_DCIM || type == MTP_OR_PTP); | 190 (type == REMOVABLE_MASS_STORAGE_WITH_DCIM || type == MTP_OR_PTP || |
| 191 type == MAC_IMAGE_CAPTURE); |
174 } | 192 } |
175 | 193 |
176 // static | 194 // static |
177 bool MediaStorageUtil::IsRemovableDevice(const std::string& device_id) { | 195 bool MediaStorageUtil::IsRemovableDevice(const std::string& device_id) { |
178 Type type; | 196 Type type; |
179 return CrackDeviceId(device_id, &type, NULL) && type != FIXED_MASS_STORAGE; | 197 return CrackDeviceId(device_id, &type, NULL) && type != FIXED_MASS_STORAGE; |
180 } | 198 } |
181 | 199 |
182 // static | 200 // static |
183 bool MediaStorageUtil::IsMassStorageDevice(const std::string& device_id) { | 201 bool MediaStorageUtil::IsMassStorageDevice(const std::string& device_id) { |
184 Type type; | 202 Type type; |
185 return CrackDeviceId(device_id, &type, NULL) && type != MTP_OR_PTP; | 203 return CrackDeviceId(device_id, &type, NULL) && |
| 204 (type == REMOVABLE_MASS_STORAGE_WITH_DCIM || |
| 205 type == REMOVABLE_MASS_STORAGE_NO_DCIM || |
| 206 type == FIXED_MASS_STORAGE); |
186 } | 207 } |
187 | 208 |
188 // static | 209 // static |
| 210 bool MediaStorageUtil::CanCreateFileSystem(const std::string& device_id, |
| 211 const FilePath& path) { |
| 212 Type type; |
| 213 if (!CrackDeviceId(device_id, &type, NULL)) |
| 214 return false; |
| 215 |
| 216 if (type == MAC_IMAGE_CAPTURE) |
| 217 return true; |
| 218 |
| 219 return path.IsAbsolute() && !path.ReferencesParent(); |
| 220 } |
| 221 |
| 222 // static |
189 void MediaStorageUtil::IsDeviceAttached(const std::string& device_id, | 223 void MediaStorageUtil::IsDeviceAttached(const std::string& device_id, |
190 const BoolCallback& callback) { | 224 const BoolCallback& callback) { |
191 Type type; | 225 Type type; |
192 std::string unique_id; | 226 std::string unique_id; |
193 if (!CrackDeviceId(device_id, &type, &unique_id)) { | 227 if (!CrackDeviceId(device_id, &type, &unique_id)) { |
194 callback.Run(false); | 228 callback.Run(false); |
195 return; | 229 return; |
196 } | 230 } |
197 | 231 |
198 if (type == FIXED_MASS_STORAGE) { | 232 if (type == FIXED_MASS_STORAGE) { |
199 // For this type, the unique_id is the path. | 233 // For this type, the unique_id is the path. |
200 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 234 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
201 base::Bind(&ValidatePathOnFileThread, | 235 base::Bind(&ValidatePathOnFileThread, |
202 FilePath::FromUTF8Unsafe(unique_id), | 236 FilePath::FromUTF8Unsafe(unique_id), |
203 callback)); | 237 callback)); |
204 } else { | 238 } else { |
205 DCHECK(type == MTP_OR_PTP || | 239 DCHECK(type == MTP_OR_PTP || |
206 type == REMOVABLE_MASS_STORAGE_WITH_DCIM || | 240 type == REMOVABLE_MASS_STORAGE_WITH_DCIM || |
207 type == REMOVABLE_MASS_STORAGE_NO_DCIM); | 241 type == REMOVABLE_MASS_STORAGE_NO_DCIM); |
208 // We should be able to find removable storage in SystemMonitor. | 242 // We should be able to find removable storage in SystemMonitor. |
209 callback.Run(!FindRemovableStorageLocationById(device_id).empty()); | 243 callback.Run(IsRemovableStorageAttached(device_id)); |
210 } | 244 } |
211 } | 245 } |
212 | 246 |
213 // static | 247 // static |
214 void MediaStorageUtil::FilterAttachedDevices(DeviceIdSet* devices, | 248 void MediaStorageUtil::FilterAttachedDevices(DeviceIdSet* devices, |
215 const base::Closure& done) { | 249 const base::Closure& done) { |
216 if (BrowserThread::CurrentlyOn(BrowserThread::FILE)) { | 250 if (BrowserThread::CurrentlyOn(BrowserThread::FILE)) { |
217 FilterAttachedDevicesOnFileThread(devices); | 251 FilterAttachedDevicesOnFileThread(devices); |
218 done.Run(); | 252 done.Run(); |
219 return; | 253 return; |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 Type type; | 337 Type type; |
304 std::string unique_id; | 338 std::string unique_id; |
305 if (!CrackDeviceId(device_id, &type, &unique_id)) | 339 if (!CrackDeviceId(device_id, &type, &unique_id)) |
306 return FilePath(); | 340 return FilePath(); |
307 | 341 |
308 if (type == FIXED_MASS_STORAGE) { | 342 if (type == FIXED_MASS_STORAGE) { |
309 // For this type, the unique_id is the path. | 343 // For this type, the unique_id is the path. |
310 return FilePath::FromUTF8Unsafe(unique_id); | 344 return FilePath::FromUTF8Unsafe(unique_id); |
311 } | 345 } |
312 | 346 |
| 347 // This should return "/" because when the prefs returns an absolute path, |
| 348 // it just smacks it on the end of whatever this method returns. |
| 349 // For ImageCapture, we're not using the path as a path anyway, so return |
| 350 // something to make the fake path arithmetic work out. |
| 351 if (type == MAC_IMAGE_CAPTURE) { |
| 352 return FilePath(kRootPath + device_id); |
| 353 } |
| 354 |
313 DCHECK(type == MTP_OR_PTP || | 355 DCHECK(type == MTP_OR_PTP || |
314 type == REMOVABLE_MASS_STORAGE_WITH_DCIM || | 356 type == REMOVABLE_MASS_STORAGE_WITH_DCIM || |
315 type == REMOVABLE_MASS_STORAGE_NO_DCIM); | 357 type == REMOVABLE_MASS_STORAGE_NO_DCIM); |
316 return FilePath(FindRemovableStorageLocationById(device_id)); | 358 return FilePath(FindRemovableStorageLocationById(device_id)); |
317 } | 359 } |
318 | 360 |
319 // static | 361 // static |
320 void MediaStorageUtil::RecordDeviceInfoHistogram(bool mass_storage, | 362 void MediaStorageUtil::RecordDeviceInfoHistogram(bool mass_storage, |
321 const std::string& device_uuid, | 363 const std::string& device_uuid, |
322 const string16& device_name) { | 364 const string16& device_name) { |
(...skipping 18 matching lines...) Expand all Loading... |
341 | 383 |
342 // static | 384 // static |
343 void MediaStorageUtil::SetGetDeviceInfoFromPathFunctionForTesting( | 385 void MediaStorageUtil::SetGetDeviceInfoFromPathFunctionForTesting( |
344 GetDeviceInfoFromPathFunction function) { | 386 GetDeviceInfoFromPathFunction function) { |
345 g_test_get_device_info_from_path_function = function; | 387 g_test_get_device_info_from_path_function = function; |
346 } | 388 } |
347 | 389 |
348 MediaStorageUtil::MediaStorageUtil() {} | 390 MediaStorageUtil::MediaStorageUtil() {} |
349 | 391 |
350 } // namespace chrome | 392 } // namespace chrome |
OLD | NEW |