OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 // chrome::MediaStorageUtil implementation. | |
6 | |
7 #include "chrome/browser/media_gallery/media_storage_util.h" | |
8 | |
9 #include <vector> | |
10 | |
11 #include "base/callback.h" | |
12 #include "base/file_util.h" | |
13 #include "base/logging.h" | |
14 #include "base/system_monitor/system_monitor.h" | |
15 #include "content/public/browser/browser_thread.h" | |
16 | |
17 namespace chrome { | |
18 | |
19 namespace { | |
20 | |
21 typedef std::vector<base::SystemMonitor::MediaDeviceInfo> MediaDevicesInfo; | |
22 | |
23 // Prefix constants for different device id spaces. | |
24 const char kUsbMassStorageWithDCIMPrefix[] = "dcim:"; | |
25 const char kUsbMassStorageNoDCIMPrefix[] = "usb:"; | |
26 const char kOtherMassStoragePrefix[] = "path:"; | |
27 const char kUsbMtpPrefix[] = "mtp:"; | |
28 | |
29 void EmptyPathIsFalseCallback(const MediaStorageUtil::BoolCallback& callback, | |
30 FilePath path) { | |
31 callback.Run(!path.empty()); | |
32 } | |
33 | |
34 void ValidatePathOnFileThread( | |
35 const FilePath& path, const MediaStorageUtil::FilePathCallback& callback) { | |
36 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); | |
37 FilePath result; | |
38 if (file_util::PathExists(path)) | |
39 result = path; | |
40 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, | |
41 base::Bind(callback, path)); | |
42 } | |
43 | |
44 // TODO(vandebo) use FilePath::AppendRelativePath instead | |
kmadhusu
2012/08/20 17:13:50
nit: TODO(vandebo):
vandebo (ex-Chrome)
2012/08/20 18:35:14
colon is optional
| |
45 // Make |path| a relative path, i.e. strip the drive letter and leading /. | |
46 FilePath MakePathRelative(const FilePath& path) { | |
47 if (!path.IsAbsolute()) | |
48 return path; | |
49 | |
50 FilePath relative; | |
51 std::vector<FilePath::StringType> components; | |
52 path.GetComponents(&components); | |
53 | |
54 // On Windows, the first component may be the drive letter with the second | |
55 // being \\. | |
56 int start = 1; | |
57 if (components[1].size() == 1 && FilePath::IsSeparator(components[1][0])) | |
58 start = 2; | |
59 | |
60 for (size_t i = start; i < components.size(); i++) | |
61 relative = relative.Append(components[i]); | |
62 return relative; | |
63 } | |
64 | |
65 } // namespace | |
66 | |
67 // static | |
68 std::string MediaStorageUtil::MakeDeviceId(Type type, | |
69 const std::string& unique_id) { | |
70 DCHECK(!unique_id.empty()); | |
71 switch (type) { | |
72 case USB_MASS_STORAGE_WITH_DCIM: | |
73 return std::string(kUsbMassStorageWithDCIMPrefix) + unique_id; | |
74 case USB_MASS_STORAGE_NO_DCIM: | |
75 return std::string(kUsbMassStorageNoDCIMPrefix) + unique_id; | |
76 case OTHER_MASS_STORAGE: | |
77 return std::string(kOtherMassStoragePrefix) + unique_id; | |
78 case USB_MTP: | |
79 return std::string(kUsbMtpPrefix) + unique_id; | |
80 default: | |
81 NOTREACHED(); | |
82 return std::string(); | |
83 } | |
84 } | |
85 | |
86 // static | |
87 void MediaStorageUtil::CrackDeviceId(const std::string& device_id, | |
88 Type* type, std::string* unique_id) { | |
89 size_t prefix_length = device_id.find_first_of(':'); | |
90 std::string prefix = device_id.substr(0, prefix_length); | |
91 | |
92 if (type) { | |
93 if (prefix == kUsbMassStorageWithDCIMPrefix) { | |
94 *type = USB_MASS_STORAGE_WITH_DCIM; | |
95 } else if (prefix == kUsbMassStorageNoDCIMPrefix) { | |
96 *type = USB_MASS_STORAGE_NO_DCIM; | |
97 } else if (prefix == kOtherMassStoragePrefix) { | |
98 *type = OTHER_MASS_STORAGE; | |
99 } else if (prefix == kUsbMtpPrefix) { | |
100 *type = USB_MTP; | |
101 } else { | |
102 NOTREACHED(); | |
103 } | |
104 } | |
105 | |
106 if (unique_id) | |
107 *unique_id = device_id.substr(prefix_length + 1); | |
108 } | |
109 | |
110 // static | |
111 bool MediaStorageUtil::IsMediaDevice(const std::string& device_id) { | |
112 Type type; | |
113 CrackDeviceId(device_id, &type, NULL); | |
114 return type == USB_MASS_STORAGE_WITH_DCIM || type == USB_MTP; | |
115 } | |
116 | |
117 // static | |
118 bool MediaStorageUtil::IsRemovableDevice(const std::string& device_id) { | |
119 Type type; | |
120 CrackDeviceId(device_id, &type, NULL); | |
121 return type != OTHER_MASS_STORAGE; | |
122 } | |
123 | |
124 // static | |
125 void MediaStorageUtil::IsDeviceAttached(const std::string& device_id, | |
126 const BoolCallback& callback) { | |
127 Type type; | |
128 std::string unique_id; | |
129 CrackDeviceId(device_id, &type, &unique_id); | |
130 | |
131 switch (type) { | |
132 case USB_MTP: // Fall through | |
133 case USB_MASS_STORAGE_WITH_DCIM: { | |
134 // We should be able to find media devices in SystemMonitor. | |
135 MediaDevicesInfo media_devices = | |
136 base::SystemMonitor::Get()->GetAttachedMediaDevices(); | |
137 for (MediaDevicesInfo::const_iterator it = media_devices.begin(); | |
138 it != media_devices.end(); | |
139 ++it) { | |
140 if (it->unique_id == device_id) { | |
141 callback.Run(true); | |
142 return; | |
143 } | |
144 } | |
145 callback.Run(false); | |
146 break; | |
147 } | |
148 case USB_MASS_STORAGE_NO_DCIM: | |
149 FindUSBDeviceById(unique_id, | |
150 base::Bind(&EmptyPathIsFalseCallback, callback)); | |
151 break; | |
152 case OTHER_MASS_STORAGE: | |
153 // For this type, the unique_id is the path. | |
154 content::BrowserThread::PostTask( | |
155 content::BrowserThread::FILE, FROM_HERE, | |
156 base::Bind(&ValidatePathOnFileThread, | |
157 FilePath::FromUTF8Unsafe(unique_id), | |
158 base::Bind(&EmptyPathIsFalseCallback, callback))); | |
159 break; | |
160 default: | |
161 NOTREACHED(); | |
162 } | |
163 } | |
164 | |
165 // static | |
166 void MediaStorageUtil::GetDeviceInfoFromPath( | |
167 const FilePath& path, const DeviceInfoCallback& callback) { | |
168 // TODO(vandebo) This needs to be implemented per platform. Below is no | |
kmadhusu
2012/08/20 17:13:50
TODO(vandebo):
| |
169 // worse than what the code already does. | |
170 // * Find mount point parent (determines relative file path) | |
171 // * Search System monitor, just in case. | |
172 // * If it's a USB device, generate device id, else use device root path as id | |
173 std::string device_id = | |
174 MakeDeviceId(OTHER_MASS_STORAGE, path.AsUTF8Unsafe()); | |
175 FilePath relative_path = MakePathRelative(path); | |
176 string16 display_name = path.BaseName().LossyDisplayName(); | |
177 | |
178 callback.Run(device_id, relative_path, display_name); | |
179 return; | |
180 } | |
181 | |
182 // static | |
183 void MediaStorageUtil::FindDevicePathById(const std::string& device_id, | |
184 const FilePathCallback& callback) { | |
185 Type type; | |
186 std::string unique_id; | |
187 CrackDeviceId(device_id, &type, &unique_id); | |
188 | |
189 switch (type) { | |
190 case USB_MTP: | |
191 callback.Run(FilePath()); | |
192 break; | |
193 case USB_MASS_STORAGE_NO_DCIM: | |
194 FindUSBDeviceById(unique_id, callback); | |
195 break; | |
196 case OTHER_MASS_STORAGE: | |
197 // For this type, the unique_id is the path. | |
198 content::BrowserThread::PostTask( | |
199 content::BrowserThread::FILE, FROM_HERE, | |
200 base::Bind(&ValidatePathOnFileThread, | |
201 FilePath::FromUTF8Unsafe(unique_id), callback)); | |
202 break; | |
203 case USB_MASS_STORAGE_WITH_DCIM: { | |
204 FilePath result; | |
205 MediaDevicesInfo media_devices = | |
206 base::SystemMonitor::Get()->GetAttachedMediaDevices(); | |
207 for (MediaDevicesInfo::const_iterator it = media_devices.begin(); | |
208 it != media_devices.end(); | |
209 ++it) { | |
210 if (it->unique_id == device_id) { | |
211 result = FilePath(it->location); | |
212 break; | |
213 } | |
214 } | |
215 callback.Run(result); | |
216 break; | |
217 } | |
218 default: | |
219 NOTREACHED(); | |
220 } | |
221 } | |
222 | |
223 MediaStorageUtil::MediaStorageUtil() {} | |
224 | |
225 // static | |
226 void MediaStorageUtil::FindUSBDeviceById(const std::string unique_id, | |
kmadhusu
2012/08/20 17:13:50
nit: const std::string&
vandebo (ex-Chrome)
2012/08/20 18:35:14
Done.
| |
227 const FilePathCallback& callback) { | |
228 // TODO(vandebo) This needs to be implemented per platform. | |
229 // Type is USB_MASS_STORAGE_NO_DCIM, so it's a device possibly mounted | |
230 // somewhere... | |
231 NOTREACHED(); | |
232 callback.Run(FilePath()); | |
233 } | |
234 | |
235 } // namespace chrome | |
OLD | NEW |