Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(378)

Side by Side Diff: chrome/browser/storage_monitor/removable_device_notifications_linux.cc

Issue 12211084: [Media Galleries] Populate volume metadata in ChromeOS/Linux (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Reset header file Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 // RemovableDeviceNotificationsLinux implementation. 5 // RemovableDeviceNotificationsLinux implementation.
6 6
7 #include "chrome/browser/storage_monitor/removable_device_notifications_linux.h" 7 #include "chrome/browser/storage_monitor/removable_device_notifications_linux.h"
8 8
9 #include <mntent.h> 9 #include <mntent.h>
10 #include <stdio.h> 10 #include <stdio.h>
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 128
129 uint64 total_size_in_bytes = 0; 129 uint64 total_size_in_bytes = 0;
130 if (!base::StringToUint64(partition_size, &total_size_in_bytes)) 130 if (!base::StringToUint64(partition_size, &total_size_in_bytes))
131 return 0; 131 return 0;
132 return (total_size_in_bytes <= kuint64max / 512) ? 132 return (total_size_in_bytes <= kuint64max / 512) ?
133 total_size_in_bytes * 512 : 0; 133 total_size_in_bytes * 512 : 0;
134 } 134 }
135 135
136 // Constructs the device name from the device properties. If the device details 136 // Constructs the device name from the device properties. If the device details
137 // are unavailable, returns an empty string. 137 // are unavailable, returns an empty string.
138 string16 GetDeviceName(struct udev_device* device) { 138 string16 GetDeviceName(struct udev_device* device,
139 string16* out_volume_label,
140 string16* out_vendor_name,
141 string16* out_model_name) {
139 std::string device_label = GetUdevDevicePropertyValue(device, kLabel); 142 std::string device_label = GetUdevDevicePropertyValue(device, kLabel);
143 std::string vendor_name = GetUdevDevicePropertyValue(device, kVendor);
144 std::string model_name = GetUdevDevicePropertyValue(device, kModel);
145 if (out_volume_label)
146 *out_volume_label = UTF8ToUTF16(device_label);
147 if (out_vendor_name)
148 *out_vendor_name = UTF8ToUTF16(vendor_name);
149 if (out_model_name)
150 *out_model_name = UTF8ToUTF16(model_name);
151
140 if (!device_label.empty() && IsStringUTF8(device_label)) 152 if (!device_label.empty() && IsStringUTF8(device_label))
141 return UTF8ToUTF16(device_label); 153 return UTF8ToUTF16(device_label);
142 154
143 device_label = GetUdevDevicePropertyValue(device, kFsUUID); 155 device_label = GetUdevDevicePropertyValue(device, kFsUUID);
144 // Keep track of device uuid, to see how often we receive empty uuid values. 156 // Keep track of device uuid, to see how often we receive empty uuid values.
145 UMA_HISTOGRAM_BOOLEAN( 157 UMA_HISTOGRAM_BOOLEAN(
146 "RemovableDeviceNotificationsLinux.device_file_system_uuid_available", 158 "RemovableDeviceNotificationsLinux.device_file_system_uuid_available",
147 !device_label.empty()); 159 !device_label.empty());
148 160
149 const string16 name = GetFullProductName( 161 const string16 name = GetFullProductName(vendor_name, model_name);
150 GetUdevDevicePropertyValue(device, kVendor),
151 GetUdevDevicePropertyValue(device, kModel));
152 162
153 const string16 device_label_utf16 = 163 const string16 device_label_utf16 =
154 (!device_label.empty() && IsStringUTF8(device_label)) ? 164 (!device_label.empty() && IsStringUTF8(device_label)) ?
155 UTF8ToUTF16(device_label) : string16(); 165 UTF8ToUTF16(device_label) : string16();
156 if (!name.empty() && !device_label_utf16.empty()) 166 if (!name.empty() && !device_label_utf16.empty())
157 return device_label_utf16 + ASCIIToUTF16(" ") + name; 167 return device_label_utf16 + ASCIIToUTF16(" ") + name;
158 return name.empty() ? device_label_utf16 : name; 168 return name.empty() ? device_label_utf16 : name;
159 } 169 }
160 170
161 // Get the device information using udev library. 171 // Get the device information using udev library.
162 // On success, returns true and fill in |unique_id|, |name|, |removable| and 172 // On success, returns true and fill in |unique_id|, |name|, |removable| and
163 // |partition_size_in_bytes|. 173 // |partition_size_in_bytes|.
164 void GetDeviceInfo(const base::FilePath& device_path, 174 void GetDeviceInfo(const base::FilePath& device_path,
165 std::string* unique_id, 175 const base::FilePath& mount_point,
176 std::string* device_id,
166 string16* name, 177 string16* name,
167 bool* removable, 178 bool* removable,
168 uint64* partition_size_in_bytes) { 179 uint64* partition_size_in_bytes,
180 string16* out_volume_label,
181 string16* out_vendor_name,
182 string16* out_model_name) {
169 DCHECK(!device_path.empty()); 183 DCHECK(!device_path.empty());
170 ScopedUdevObject udev_obj(udev_new()); 184 ScopedUdevObject udev_obj(udev_new());
171 if (!udev_obj.get()) { 185 if (!udev_obj.get()) {
172 RecordGetDeviceInfoResult(false); 186 RecordGetDeviceInfoResult(false);
173 return; 187 return;
174 } 188 }
175 189
176 struct stat device_stat; 190 struct stat device_stat;
177 if (stat(device_path.value().c_str(), &device_stat) < 0) { 191 if (stat(device_path.value().c_str(), &device_stat) < 0) {
178 RecordGetDeviceInfoResult(false); 192 RecordGetDeviceInfoResult(false);
(...skipping 10 matching lines...) Expand all
189 return; // Not a supported type. 203 return; // Not a supported type.
190 } 204 }
191 205
192 ScopedUdevDeviceObject device( 206 ScopedUdevDeviceObject device(
193 udev_device_new_from_devnum(udev_obj, device_type, device_stat.st_rdev)); 207 udev_device_new_from_devnum(udev_obj, device_type, device_stat.st_rdev));
194 if (!device.get()) { 208 if (!device.get()) {
195 RecordGetDeviceInfoResult(false); 209 RecordGetDeviceInfoResult(false);
196 return; 210 return;
197 } 211 }
198 212
213 string16 volume_label;
214 string16 vendor_name;
215 string16 model_name;
216 string16 device_name = GetDeviceName(device, &volume_label,
217 &vendor_name, &model_name);
199 if (name) 218 if (name)
200 *name = GetDeviceName(device); 219 *name = device_name;
201 220
202 if (unique_id) 221 std::string unique_id = MakeDeviceUniqueId(device);
203 *unique_id = MakeDeviceUniqueId(device); 222 MediaStorageUtil::RecordDeviceInfoHistogram(true, unique_id, device_name);
204 223
224 const char* value = udev_device_get_sysattr_value(device,
225 kRemovableSysAttr);
226 if (!value) {
227 // |parent_device| is owned by |device| and does not need to be cleaned
228 // up.
229 struct udev_device* parent_device =
230 udev_device_get_parent_with_subsystem_devtype(device,
231 kBlockSubsystemKey,
232 kDiskDeviceTypeKey);
233 value = udev_device_get_sysattr_value(parent_device, kRemovableSysAttr);
234 }
235 bool is_removable = (value && atoi(value) == 1);
205 if (removable) { 236 if (removable) {
206 const char* value = udev_device_get_sysattr_value(device, 237 *removable = is_removable;
207 kRemovableSysAttr);
208 if (!value) {
209 // |parent_device| is owned by |device| and does not need to be cleaned
210 // up.
211 struct udev_device* parent_device =
212 udev_device_get_parent_with_subsystem_devtype(device,
213 kBlockSubsystemKey,
214 kDiskDeviceTypeKey);
215 value = udev_device_get_sysattr_value(parent_device, kRemovableSysAttr);
216 }
217 *removable = (value && atoi(value) == 1);
218 } 238 }
219 239
240 bool has_dcim = IsMediaDevice(mount_point.value());
vandebo (ex-Chrome) 2013/03/01 22:21:48 This block should all be in if(device_id) {
Greg Billock 2013/03/05 19:20:55 Done.
241 MediaStorageUtil::Type type = MediaStorageUtil::FIXED_MASS_STORAGE;
242 if (is_removable) {
243 if (has_dcim)
244 type = MediaStorageUtil::REMOVABLE_MASS_STORAGE_WITH_DCIM;
245 else
246 type = MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM;
247 }
248 if (device_id)
249 *device_id = MediaStorageUtil::MakeDeviceId(type, unique_id);
250
220 if (partition_size_in_bytes) 251 if (partition_size_in_bytes)
221 *partition_size_in_bytes = GetDeviceStorageSize(device_path, device); 252 *partition_size_in_bytes = GetDeviceStorageSize(device_path, device);
222 RecordGetDeviceInfoResult(true); 253 RecordGetDeviceInfoResult(true);
223 } 254 }
224 255
225 } // namespace 256 } // namespace
226 257
227 RemovableDeviceNotificationsLinux::RemovableDeviceNotificationsLinux( 258 RemovableDeviceNotificationsLinux::RemovableDeviceNotificationsLinux(
228 const base::FilePath& path) 259 const base::FilePath& path)
229 : initialized_(false), 260 : initialized_(false),
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 if (!path.IsAbsolute()) 292 if (!path.IsAbsolute())
262 return false; 293 return false;
263 294
264 base::FilePath current = path; 295 base::FilePath current = path;
265 while (!ContainsKey(mount_info_map_, current) && current != current.DirName()) 296 while (!ContainsKey(mount_info_map_, current) && current != current.DirName())
266 current = current.DirName(); 297 current = current.DirName();
267 298
268 MountMap::const_iterator mount_info = mount_info_map_.find(current); 299 MountMap::const_iterator mount_info = mount_info_map_.find(current);
269 if (mount_info == mount_info_map_.end()) 300 if (mount_info == mount_info_map_.end())
270 return false; 301 return false;
271 302 if (device_info)
272 if (device_info) { 303 *device_info = mount_info->second;
273 device_info->device_id = mount_info->second.device_id;
274 device_info->name = mount_info->second.device_name;
275 device_info->location = current.value();
276 }
277 return true; 304 return true;
278 } 305 }
279 306
280 uint64 RemovableDeviceNotificationsLinux::GetStorageSize( 307 uint64 RemovableDeviceNotificationsLinux::GetStorageSize(
281 const std::string& location) const { 308 const std::string& location) const {
282 MountMap::const_iterator mount_info = mount_info_map_.find( 309 MountMap::const_iterator mount_info = mount_info_map_.find(
283 base::FilePath(location)); 310 base::FilePath(location));
284 return (mount_info != mount_info_map_.end()) ? 311 return (mount_info != mount_info_map_.end()) ?
285 mount_info->second.partition_size_in_bytes : 0; 312 mount_info->second.total_size_in_bytes : 0;
286 } 313 }
287 314
288 void RemovableDeviceNotificationsLinux::OnFilePathChanged( 315 void RemovableDeviceNotificationsLinux::OnFilePathChanged(
289 const base::FilePath& path, 316 const base::FilePath& path,
290 bool error) { 317 bool error) {
291 if (path != mtab_path_) { 318 if (path != mtab_path_) {
292 // This cannot happen unless FilePathWatcher is buggy. Just ignore this 319 // This cannot happen unless FilePathWatcher is buggy. Just ignore this
293 // notification and do nothing. 320 // notification and do nothing.
294 NOTREACHED(); 321 NOTREACHED();
295 return; 322 return;
296 } 323 }
297 if (error) { 324 if (error) {
298 LOG(ERROR) << "Error watching " << mtab_path_.value(); 325 LOG(ERROR) << "Error watching " << mtab_path_.value();
299 return; 326 return;
300 } 327 }
301 328
302 UpdateMtab(); 329 UpdateMtab();
303 } 330 }
304 331
305 RemovableDeviceNotificationsLinux::MountPointInfo::MountPointInfo() 332 base::FilePath RemovableDeviceNotificationsLinux::GetDeviceForMountPoint(
vandebo (ex-Chrome) 2013/03/01 22:21:48 Not a fan of this. Yes all the information is her
Greg Billock 2013/03/05 19:20:55 I think it's complicated because of the priority m
vandebo (ex-Chrome) 2013/03/06 01:34:54 So the way it was before was storing some redundan
306 : partition_size_in_bytes(0) { 333 const base::FilePath& mount_point) {
334 for (MountPriorityMap::const_iterator iter = mount_priority_map_.begin();
335 iter != mount_priority_map_.end(); ++iter) {
336 for (ReferencedMountPoint::const_iterator itermp = iter->second.begin();
337 itermp != iter->second.end(); ++itermp) {
338 if (itermp->first == mount_point)
339 return iter->first;
340 }
341 }
342 return base::FilePath();
307 } 343 }
308 344
309 void RemovableDeviceNotificationsLinux::InitOnFileThread() { 345 void RemovableDeviceNotificationsLinux::InitOnFileThread() {
310 DCHECK(!initialized_); 346 DCHECK(!initialized_);
311 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 347 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
312 initialized_ = true; 348 initialized_ = true;
313 349
314 // The callback passed to Watch() has to be unretained. Otherwise 350 // The callback passed to Watch() has to be unretained. Otherwise
315 // RemovableDeviceNotificationsLinux will live longer than expected, and 351 // RemovableDeviceNotificationsLinux will live longer than expected, and
316 // FilePathWatcher will get in trouble at shutdown time. 352 // FilePathWatcher will get in trouble at shutdown time.
(...skipping 15 matching lines...) Expand all
332 MountPointDeviceMap new_mtab; 368 MountPointDeviceMap new_mtab;
333 ReadMtab(mtab_path_, known_file_systems_, &new_mtab); 369 ReadMtab(mtab_path_, known_file_systems_, &new_mtab);
334 370
335 // Check existing mtab entries for unaccounted mount points. 371 // Check existing mtab entries for unaccounted mount points.
336 // These mount points must have been removed in the new mtab. 372 // These mount points must have been removed in the new mtab.
337 std::list<base::FilePath> mount_points_to_erase; 373 std::list<base::FilePath> mount_points_to_erase;
338 std::list<base::FilePath> multiple_mounted_devices_needing_reattachment; 374 std::list<base::FilePath> multiple_mounted_devices_needing_reattachment;
339 for (MountMap::const_iterator old_iter = mount_info_map_.begin(); 375 for (MountMap::const_iterator old_iter = mount_info_map_.begin();
340 old_iter != mount_info_map_.end(); ++old_iter) { 376 old_iter != mount_info_map_.end(); ++old_iter) {
341 const base::FilePath& mount_point = old_iter->first; 377 const base::FilePath& mount_point = old_iter->first;
342 const base::FilePath& mount_device = old_iter->second.mount_device; 378 const base::FilePath& mount_device = GetDeviceForMountPoint(mount_point);
343 MountPointDeviceMap::iterator new_iter = new_mtab.find(mount_point); 379 MountPointDeviceMap::iterator new_iter = new_mtab.find(mount_point);
344 // |mount_point| not in |new_mtab| or |mount_device| is no longer mounted at 380 // |mount_point| not in |new_mtab| or |mount_device| is no longer mounted at
345 // |mount_point|. 381 // |mount_point|.
346 if (new_iter == new_mtab.end() || (new_iter->second != mount_device)) { 382 if (new_iter == new_mtab.end() || (new_iter->second != mount_device)) {
347 MountPriorityMap::iterator priority = 383 MountPriorityMap::iterator priority =
348 mount_priority_map_.find(mount_device); 384 mount_priority_map_.find(mount_device);
349 DCHECK(priority != mount_priority_map_.end()); 385 DCHECK(priority != mount_priority_map_.end());
350 ReferencedMountPoint::const_iterator has_priority = 386 ReferencedMountPoint::const_iterator has_priority =
351 priority->second.find(mount_point); 387 priority->second.find(mount_point);
352 if (MediaStorageUtil::IsRemovableDevice(old_iter->second.device_id)) { 388 if (MediaStorageUtil::IsRemovableDevice(old_iter->second.device_id)) {
(...skipping 26 matching lines...) Expand all
379 // mount points. 415 // mount points.
380 for (std::list<base::FilePath>::const_iterator it = 416 for (std::list<base::FilePath>::const_iterator it =
381 multiple_mounted_devices_needing_reattachment.begin(); 417 multiple_mounted_devices_needing_reattachment.begin();
382 it != multiple_mounted_devices_needing_reattachment.end(); 418 it != multiple_mounted_devices_needing_reattachment.end();
383 ++it) { 419 ++it) {
384 ReferencedMountPoint::iterator first_mount_point_info = 420 ReferencedMountPoint::iterator first_mount_point_info =
385 mount_priority_map_.find(*it)->second.begin(); 421 mount_priority_map_.find(*it)->second.begin();
386 const base::FilePath& mount_point = first_mount_point_info->first; 422 const base::FilePath& mount_point = first_mount_point_info->first;
387 first_mount_point_info->second = true; 423 first_mount_point_info->second = true;
388 424
389 const MountPointInfo& mount_info = 425 const StorageInfo& mount_info =
390 mount_info_map_.find(mount_point)->second; 426 mount_info_map_.find(mount_point)->second;
391 DCHECK(MediaStorageUtil::IsRemovableDevice(mount_info.device_id)); 427 DCHECK(MediaStorageUtil::IsRemovableDevice(mount_info.device_id));
392 receiver()->ProcessAttach(StorageInfo( 428 receiver()->ProcessAttach(mount_info);
393 mount_info.device_id, mount_info.device_name, mount_point.value()));
394 } 429 }
395 430
396 // Check new mtab entries against existing ones. 431 // Check new mtab entries against existing ones.
397 for (MountPointDeviceMap::iterator new_iter = new_mtab.begin(); 432 for (MountPointDeviceMap::iterator new_iter = new_mtab.begin();
398 new_iter != new_mtab.end(); ++new_iter) { 433 new_iter != new_mtab.end(); ++new_iter) {
399 const base::FilePath& mount_point = new_iter->first; 434 const base::FilePath& mount_point = new_iter->first;
400 const base::FilePath& mount_device = new_iter->second; 435 const base::FilePath& mount_device = new_iter->second;
401 MountMap::iterator old_iter = mount_info_map_.find(mount_point); 436 MountMap::iterator old_iter = mount_info_map_.find(mount_point);
402 if (old_iter == mount_info_map_.end() || 437 if (old_iter == mount_info_map_.end() ||
403 old_iter->second.mount_device != mount_device) { 438 GetDeviceForMountPoint(old_iter->first) != mount_device) {
404 // New mount point found or an existing mount point found with a new 439 // New mount point found or an existing mount point found with a new
405 // device. 440 // device.
406 AddNewMount(mount_device, mount_point); 441 AddNewMount(mount_device, mount_point);
407 } 442 }
408 } 443 }
409 } 444 }
410 445
411 void RemovableDeviceNotificationsLinux::AddNewMount( 446 void RemovableDeviceNotificationsLinux::AddNewMount(
412 const base::FilePath& mount_device, const base::FilePath& mount_point) { 447 const base::FilePath& mount_device, const base::FilePath& mount_point) {
413 MountPriorityMap::iterator priority = 448 MountPriorityMap::iterator priority =
414 mount_priority_map_.find(mount_device); 449 mount_priority_map_.find(mount_device);
415 if (priority != mount_priority_map_.end()) { 450 if (priority != mount_priority_map_.end()) {
416 const base::FilePath& other_mount_point = priority->second.begin()->first; 451 const base::FilePath& other_mount_point = priority->second.begin()->first;
417 priority->second[mount_point] = false; 452 priority->second[mount_point] = false;
418 mount_info_map_[mount_point] = 453 mount_info_map_[mount_point] =
419 mount_info_map_.find(other_mount_point)->second; 454 mount_info_map_.find(other_mount_point)->second;
420 return; 455 return;
421 } 456 }
422 457
423 std::string unique_id; 458 std::string device_id;
424 string16 name; 459 string16 name;
425 bool removable; 460 bool removable;
426 uint64 partition_size_in_bytes; 461 uint64 partition_size_in_bytes;
427 get_device_info_func_(mount_device, &unique_id, &name, &removable, 462 string16 volume_label;
428 &partition_size_in_bytes); 463 string16 vendor_name;
464 string16 model_name;
465 get_device_info_func_(mount_device, mount_point, &device_id, &name,
466 &removable, &partition_size_in_bytes,
467 &volume_label, &vendor_name, &model_name);
429 468
430 // Keep track of device info details to see how often we get invalid values. 469 // Keep track of device info details to see how often we get invalid values.
431 MediaStorageUtil::RecordDeviceInfoHistogram(true, unique_id, name); 470 if (device_id.empty() || name.empty())
432 if (unique_id.empty() || name.empty())
433 return; 471 return;
434 472
435 bool has_dcim = IsMediaDevice(mount_point.value()); 473 StorageInfo mount_point_info;
vandebo (ex-Chrome) 2013/03/01 22:21:48 use the constructor?
Greg Billock 2013/03/05 19:20:55 Done.
436 MediaStorageUtil::Type type;
437 if (removable) {
438 if (has_dcim) {
439 type = MediaStorageUtil::REMOVABLE_MASS_STORAGE_WITH_DCIM;
440 } else {
441 type = MediaStorageUtil::REMOVABLE_MASS_STORAGE_NO_DCIM;
442 }
443 } else {
444 type = MediaStorageUtil::FIXED_MASS_STORAGE;
445 }
446 std::string device_id = MediaStorageUtil::MakeDeviceId(type, unique_id);
447
448 MountPointInfo mount_point_info;
449 mount_point_info.mount_device = mount_device;
450 mount_point_info.device_id = device_id; 474 mount_point_info.device_id = device_id;
451 mount_point_info.device_name = name; 475 mount_point_info.location = mount_point.value();
452 mount_point_info.partition_size_in_bytes = partition_size_in_bytes; 476 mount_point_info.name = name;
477 mount_point_info.total_size_in_bytes = partition_size_in_bytes;
478 mount_point_info.storage_label = volume_label;
479 mount_point_info.vendor_name = vendor_name;
480 mount_point_info.model_name = model_name;
453 481
454 mount_info_map_[mount_point] = mount_point_info; 482 mount_info_map_[mount_point] = mount_point_info;
455 mount_priority_map_[mount_device][mount_point] = removable; 483 mount_priority_map_[mount_device][mount_point] = removable;
456 484
457 if (removable) { 485 if (removable) {
458 receiver()->ProcessAttach(StorageInfo( 486 receiver()->ProcessAttach(StorageInfo(
459 device_id, GetDisplayNameForDevice(partition_size_in_bytes, name), 487 device_id, GetDisplayNameForDevice(partition_size_in_bytes, name),
460 mount_point.value())); 488 mount_point.value()));
461 } 489 }
462 } 490 }
463 491
464 } // namespace chrome 492 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698