| 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 #include "chrome/browser/system_monitor/media_transfer_protocol_device_observer_
chromeos.h" | 5 #include "chrome/browser/system_monitor/media_transfer_protocol_device_observer_
chromeos.h" |
| 6 | 6 |
| 7 #include "base/file_path.h" |
| 7 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
| 8 #include "base/string_number_conversions.h" | 9 #include "base/string_number_conversions.h" |
| 9 #include "base/string_split.h" | 10 #include "base/string_split.h" |
| 10 #include "base/stringprintf.h" | 11 #include "base/stringprintf.h" |
| 11 #include "base/system_monitor/system_monitor.h" | |
| 12 #include "base/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
| 13 #include "chrome/browser/chromeos/mtp/media_transfer_protocol_manager.h" | 13 #include "chrome/browser/chromeos/mtp/media_transfer_protocol_manager.h" |
| 14 #include "chrome/browser/system_monitor/media_storage_util.h" | 14 #include "chrome/browser/system_monitor/media_storage_util.h" |
| 15 #include "chrome/browser/system_monitor/removable_device_constants.h" | 15 #include "chrome/browser/system_monitor/removable_device_constants.h" |
| 16 #include "chromeos/dbus/mtp_storage_info.pb.h" | 16 #include "chromeos/dbus/mtp_storage_info.pb.h" |
| 17 | 17 |
| 18 namespace chromeos { | 18 namespace chromeos { |
| 19 namespace mtp { | 19 namespace mtp { |
| 20 | 20 |
| 21 using base::SystemMonitor; |
| 21 using chrome::MediaStorageUtil; | 22 using chrome::MediaStorageUtil; |
| 22 | 23 |
| 23 namespace { | 24 namespace { |
| 24 | 25 |
| 26 static MediaTransferProtocolDeviceObserverCros* g_mtp_device_observer = NULL; |
| 27 |
| 25 // Device root path constant. | 28 // Device root path constant. |
| 26 const char kRootPath[] = "/"; | 29 const char kRootPath[] = "/"; |
| 27 | 30 |
| 31 // Constructs and returns the location of the device using the |storage_name|. |
| 32 std::string GetDeviceLocationFromStorageName(const std::string& storage_name) { |
| 33 // Construct a dummy device path using the storage name. This is only used |
| 34 // for registering device media file system. |
| 35 // E.g.: If the |storage_name| is "usb:2,2:12345" then "/usb:2,2:12345" is the |
| 36 // device location. |
| 37 DCHECK(!storage_name.empty()); |
| 38 return kRootPath + storage_name; |
| 39 } |
| 40 |
| 28 // Returns the storage identifier of the device from the given |storage_name|. | 41 // Returns the storage identifier of the device from the given |storage_name|. |
| 29 // E.g. If the |storage_name| is "usb:2,2:65537", the storage identifier is | 42 // E.g. If the |storage_name| is "usb:2,2:65537", the storage identifier is |
| 30 // "65537". | 43 // "65537". |
| 31 std::string GetStorageIdFromStorageName(const std::string& storage_name) { | 44 std::string GetStorageIdFromStorageName(const std::string& storage_name) { |
| 32 std::vector<std::string> name_parts; | 45 std::vector<std::string> name_parts; |
| 33 base::SplitString(storage_name, ':', &name_parts); | 46 base::SplitString(storage_name, ':', &name_parts); |
| 34 return name_parts.size() == 3 ? name_parts[2] : std::string(); | 47 return name_parts.size() == 3 ? name_parts[2] : std::string(); |
| 35 } | 48 } |
| 36 | 49 |
| 37 // Returns a unique device id from the given |storage_info|. | 50 // Returns a unique device id from the given |storage_info|. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 65 std::string device_label; | 78 std::string device_label; |
| 66 const std::string& vendor_name = storage_info.vendor(); | 79 const std::string& vendor_name = storage_info.vendor(); |
| 67 device_label = vendor_name; | 80 device_label = vendor_name; |
| 68 | 81 |
| 69 const std::string& product_name = storage_info.product(); | 82 const std::string& product_name = storage_info.product(); |
| 70 if (!product_name.empty()) { | 83 if (!product_name.empty()) { |
| 71 if (!device_label.empty()) | 84 if (!device_label.empty()) |
| 72 device_label += chrome::kSpaceDelim; | 85 device_label += chrome::kSpaceDelim; |
| 73 device_label += product_name; | 86 device_label += product_name; |
| 74 } | 87 } |
| 88 |
| 89 // Add the data store id to the device label. |
| 90 if (!device_label.empty()) { |
| 91 const std::string& volume_id = storage_info.volume_identifier(); |
| 92 if (!volume_id.empty()) { |
| 93 // TODO(kmadhusu): Use StringPrintf here and on line 98. |
| 94 device_label += chrome::kLeftParen + volume_id + chrome::kRightParen; |
| 95 } else { |
| 96 const std::string data_store_id = |
| 97 GetStorageIdFromStorageName(storage_info.storage_name()); |
| 98 if (!data_store_id.empty()) { |
| 99 device_label += chrome::kLeftParen + data_store_id + |
| 100 chrome::kRightParen; |
| 101 } |
| 102 } |
| 103 } |
| 75 return UTF8ToUTF16(device_label); | 104 return UTF8ToUTF16(device_label); |
| 76 } | 105 } |
| 77 | 106 |
| 78 // Helper function to get the device storage details such as device id, label | 107 // Helper function to get the device storage details such as device id, label |
| 79 // and location. On success and fills in |id|, |label| and |location|. | 108 // and location. On success and fills in |id|, |label| and |location|. |
| 80 void GetStorageInfo(const std::string& storage_name, | 109 void GetStorageInfo(const std::string& storage_name, |
| 81 std::string* id, | 110 std::string* id, |
| 82 string16* label, | 111 string16* label, |
| 83 std::string* location) { | 112 std::string* location) { |
| 84 DCHECK(!storage_name.empty()); | 113 DCHECK(!storage_name.empty()); |
| 85 MediaTransferProtocolManager* mtp_manager = | 114 MediaTransferProtocolManager* mtp_manager = |
| 86 MediaTransferProtocolManager::GetInstance(); | 115 MediaTransferProtocolManager::GetInstance(); |
| 87 DCHECK(mtp_manager); | 116 DCHECK(mtp_manager); |
| 88 const MtpStorageInfo* storage_info = | 117 const MtpStorageInfo* storage_info = |
| 89 mtp_manager->GetStorageInfo(storage_name); | 118 mtp_manager->GetStorageInfo(storage_name); |
| 90 | 119 |
| 91 if (!storage_info) | 120 if (!storage_info) |
| 92 return; | 121 return; |
| 93 | 122 |
| 94 if (id) | 123 if (id) |
| 95 *id = GetDeviceIdFromStorageInfo(*storage_info); | 124 *id = GetDeviceIdFromStorageInfo(*storage_info); |
| 96 | 125 |
| 97 if (label) | 126 if (label) |
| 98 *label = GetDeviceLabelFromStorageInfo(*storage_info); | 127 *label = GetDeviceLabelFromStorageInfo(*storage_info); |
| 99 | 128 |
| 100 // Construct a dummy device path using the storage name. This is only used | 129 |
| 101 // for registering device media file system. | |
| 102 // E.g.: /usb:2,2:12345 | |
| 103 if (location) | 130 if (location) |
| 104 *location = kRootPath + storage_name; | 131 *location = GetDeviceLocationFromStorageName(storage_name); |
| 105 } | 132 } |
| 106 | 133 |
| 107 } // namespace | 134 } // namespace |
| 108 | 135 |
| 109 MediaTransferProtocolDeviceObserverCros:: | 136 MediaTransferProtocolDeviceObserverCros:: |
| 110 MediaTransferProtocolDeviceObserverCros() | 137 MediaTransferProtocolDeviceObserverCros() |
| 111 : get_storage_info_func_(&GetStorageInfo) { | 138 : get_storage_info_func_(&GetStorageInfo) { |
| 139 DCHECK(!g_mtp_device_observer); |
| 140 g_mtp_device_observer = this; |
| 141 |
| 112 MediaTransferProtocolManager* mtp_manager = | 142 MediaTransferProtocolManager* mtp_manager = |
| 113 MediaTransferProtocolManager::GetInstance(); | 143 MediaTransferProtocolManager::GetInstance(); |
| 114 if (mtp_manager) | 144 if (mtp_manager) |
| 115 mtp_manager->AddObserver(this); | 145 mtp_manager->AddObserver(this); |
| 116 EnumerateStorages(); | 146 EnumerateStorages(); |
| 117 } | 147 } |
| 118 | 148 |
| 119 // This constructor is only used by unit tests. | 149 // This constructor is only used by unit tests. |
| 120 MediaTransferProtocolDeviceObserverCros:: | 150 MediaTransferProtocolDeviceObserverCros:: |
| 121 MediaTransferProtocolDeviceObserverCros( | 151 MediaTransferProtocolDeviceObserverCros( |
| 122 GetStorageInfoFunc get_storage_info_func) | 152 GetStorageInfoFunc get_storage_info_func) |
| 123 : get_storage_info_func_(get_storage_info_func) { | 153 : get_storage_info_func_(get_storage_info_func) { |
| 124 // In unit tests, we don't have a media transfer protocol manager. | 154 // In unit tests, we don't have a media transfer protocol manager. |
| 125 DCHECK(!MediaTransferProtocolManager::GetInstance()); | 155 DCHECK(!MediaTransferProtocolManager::GetInstance()); |
| 156 DCHECK(!g_mtp_device_observer); |
| 157 g_mtp_device_observer = this; |
| 126 } | 158 } |
| 127 | 159 |
| 128 MediaTransferProtocolDeviceObserverCros:: | 160 MediaTransferProtocolDeviceObserverCros:: |
| 129 ~MediaTransferProtocolDeviceObserverCros() { | 161 ~MediaTransferProtocolDeviceObserverCros() { |
| 162 DCHECK_EQ(this, g_mtp_device_observer); |
| 163 g_mtp_device_observer = NULL; |
| 164 |
| 130 MediaTransferProtocolManager* mtp_manager = | 165 MediaTransferProtocolManager* mtp_manager = |
| 131 MediaTransferProtocolManager::GetInstance(); | 166 MediaTransferProtocolManager::GetInstance(); |
| 132 if (mtp_manager) | 167 if (mtp_manager) |
| 133 mtp_manager->RemoveObserver(this); | 168 mtp_manager->RemoveObserver(this); |
| 134 } | 169 } |
| 135 | 170 |
| 171 // static |
| 172 MediaTransferProtocolDeviceObserverCros* |
| 173 MediaTransferProtocolDeviceObserverCros::GetInstance() { |
| 174 DCHECK(g_mtp_device_observer != NULL); |
| 175 return g_mtp_device_observer; |
| 176 } |
| 177 |
| 178 bool MediaTransferProtocolDeviceObserverCros::GetStorageInfoForPath( |
| 179 const FilePath& path, |
| 180 SystemMonitor::RemovableStorageInfo* storage_info) const { |
| 181 if (!path.IsAbsolute()) |
| 182 return false; |
| 183 |
| 184 std::vector<FilePath::StringType> path_components; |
| 185 path.GetComponents(&path_components); |
| 186 if (path_components.size() < 2) |
| 187 return false; |
| 188 |
| 189 // First and second component of the path specifies the device location. |
| 190 // E.g.: If |path| is "/usb:2,2:65537/DCIM/Folder_a", "/usb:2,2:65537" is the |
| 191 // device location. |
| 192 StorageLocationToInfoMap::const_iterator info_it = |
| 193 storage_map_.find(GetDeviceLocationFromStorageName(path_components[1])); |
| 194 if (info_it == storage_map_.end()) |
| 195 return false; |
| 196 |
| 197 if (storage_info) |
| 198 *storage_info = info_it->second; |
| 199 return true; |
| 200 } |
| 201 |
| 136 // MediaTransferProtocolManager::Observer override. | 202 // MediaTransferProtocolManager::Observer override. |
| 137 void MediaTransferProtocolDeviceObserverCros::StorageChanged( | 203 void MediaTransferProtocolDeviceObserverCros::StorageChanged( |
| 138 bool is_attached, | 204 bool is_attached, |
| 139 const std::string& storage_name) { | 205 const std::string& storage_name) { |
| 140 DCHECK(!storage_name.empty()); | 206 DCHECK(!storage_name.empty()); |
| 141 | 207 |
| 142 base::SystemMonitor* system_monitor = base::SystemMonitor::Get(); | 208 SystemMonitor* system_monitor = SystemMonitor::Get(); |
| 143 DCHECK(system_monitor); | 209 DCHECK(system_monitor); |
| 144 | 210 |
| 145 // New storage is attached. | 211 // New storage is attached. |
| 146 if (is_attached) { | 212 if (is_attached) { |
| 147 std::string device_id; | 213 std::string device_id; |
| 148 string16 device_name; | 214 string16 device_name; |
| 149 std::string location; | 215 std::string location; |
| 150 get_storage_info_func_(storage_name, &device_id, &device_name, &location); | 216 get_storage_info_func_(storage_name, &device_id, &device_name, &location); |
| 151 | 217 |
| 152 // Keep track of device id and device name to see how often we receive | 218 // Keep track of device id and device name to see how often we receive |
| 153 // empty values. | 219 // empty values. |
| 154 MediaStorageUtil::RecordDeviceInfoHistogram(false, device_id, device_name); | 220 MediaStorageUtil::RecordDeviceInfoHistogram(false, device_id, device_name); |
| 155 if (device_id.empty() || device_name.empty()) | 221 if (device_id.empty() || device_name.empty()) |
| 156 return; | 222 return; |
| 157 | 223 |
| 158 DCHECK(!ContainsKey(storage_map_, storage_name)); | 224 DCHECK(!ContainsKey(storage_map_, location)); |
| 159 storage_map_[storage_name] = device_id; | 225 |
| 226 SystemMonitor::RemovableStorageInfo storage_info(device_id, device_name, |
| 227 location); |
| 228 storage_map_[location] = storage_info; |
| 160 system_monitor->ProcessRemovableStorageAttached(device_id, device_name, | 229 system_monitor->ProcessRemovableStorageAttached(device_id, device_name, |
| 161 location); | 230 location); |
| 162 } else { | 231 } else { |
| 163 // Existing storage is detached. | 232 // Existing storage is detached. |
| 164 StorageNameToIdMap::iterator it = storage_map_.find(storage_name); | 233 StorageLocationToInfoMap::iterator it = |
| 234 storage_map_.find(GetDeviceLocationFromStorageName(storage_name)); |
| 165 if (it == storage_map_.end()) | 235 if (it == storage_map_.end()) |
| 166 return; | 236 return; |
| 167 system_monitor->ProcessRemovableStorageDetached(it->second); | 237 system_monitor->ProcessRemovableStorageDetached(it->second.device_id); |
| 168 storage_map_.erase(it); | 238 storage_map_.erase(it); |
| 169 } | 239 } |
| 170 } | 240 } |
| 171 | 241 |
| 172 void MediaTransferProtocolDeviceObserverCros::EnumerateStorages() { | 242 void MediaTransferProtocolDeviceObserverCros::EnumerateStorages() { |
| 173 typedef std::vector<std::string> StorageList; | 243 typedef std::vector<std::string> StorageList; |
| 174 MediaTransferProtocolManager* mtp_manager = | 244 MediaTransferProtocolManager* mtp_manager = |
| 175 MediaTransferProtocolManager::GetInstance(); | 245 MediaTransferProtocolManager::GetInstance(); |
| 176 DCHECK(mtp_manager); | 246 DCHECK(mtp_manager); |
| 177 StorageList storages = mtp_manager->GetStorages(); | 247 StorageList storages = mtp_manager->GetStorages(); |
| 178 for (StorageList::const_iterator storage_iter = storages.begin(); | 248 for (StorageList::const_iterator storage_iter = storages.begin(); |
| 179 storage_iter != storages.end(); ++storage_iter) { | 249 storage_iter != storages.end(); ++storage_iter) { |
| 180 StorageChanged(true, *storage_iter); | 250 StorageChanged(true, *storage_iter); |
| 181 } | 251 } |
| 182 } | 252 } |
| 183 | 253 |
| 184 } // namespace mtp | 254 } // namespace mtp |
| 185 } // namespace chromeos | 255 } // namespace chromeos |
| OLD | NEW |