OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/media_galleries/win/mtp_device_operations_util.h" | 5 #include "chrome/browser/media_galleries/win/mtp_device_operations_util.h" |
6 | 6 |
7 #include <portabledevice.h> | 7 #include <portabledevice.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 | 10 |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 HRESULT hr = properties_values->GetStringValue(WPD_OBJECT_ORIGINAL_FILE_NAME, | 111 HRESULT hr = properties_values->GetStringValue(WPD_OBJECT_ORIGINAL_FILE_NAME, |
112 &buffer); | 112 &buffer); |
113 if (FAILED(hr)) | 113 if (FAILED(hr)) |
114 hr = properties_values->GetStringValue(WPD_OBJECT_NAME, &buffer); | 114 hr = properties_values->GetStringValue(WPD_OBJECT_NAME, &buffer); |
115 if (SUCCEEDED(hr)) | 115 if (SUCCEEDED(hr)) |
116 result.assign(buffer); | 116 result.assign(buffer); |
117 return result; | 117 return result; |
118 } | 118 } |
119 | 119 |
120 // Gets the last modified time of the object from the property key values | 120 // Gets the last modified time of the object from the property key values |
121 // specified by the |properties_values|. On success, returns true and fills in | 121 // specified by the |properties_values|. On success, fills in |
122 // |last_modified_time|. | 122 // |last_modified_time|. |
123 bool GetLastModifiedTime(IPortableDeviceValues* properties_values, | 123 void GetLastModifiedTime(IPortableDeviceValues* properties_values, |
124 base::Time* last_modified_time) { | 124 base::Time* last_modified_time) { |
125 DCHECK(properties_values); | 125 DCHECK(properties_values); |
126 DCHECK(last_modified_time); | 126 DCHECK(last_modified_time); |
127 base::win::ScopedPropVariant last_modified_date; | 127 base::win::ScopedPropVariant last_modified_date; |
128 HRESULT hr = properties_values->GetValue(WPD_OBJECT_DATE_MODIFIED, | 128 HRESULT hr = properties_values->GetValue(WPD_OBJECT_DATE_MODIFIED, |
129 last_modified_date.Receive()); | 129 last_modified_date.Receive()); |
130 if (FAILED(hr)) | 130 if (FAILED(hr)) |
131 return false; | 131 return; |
132 | 132 |
133 bool last_modified_time_set = (last_modified_date.get().vt == VT_DATE); | 133 // Some PTP devices don't provide an mtime. Try using the ctime instead. |
134 if (last_modified_time_set) { | 134 if (last_modified_date.get().vt != VT_DATE) { |
135 SYSTEMTIME system_time; | 135 last_modified_date.Reset(); |
136 FILETIME file_time; | 136 HRESULT hr = properties_values->GetValue(WPD_OBJECT_DATE_CREATED, |
137 if (VariantTimeToSystemTime(last_modified_date.get().date, &system_time) && | 137 last_modified_date.Receive()); |
138 SystemTimeToFileTime(&system_time, &file_time)) { | 138 if (FAILED(hr)) |
139 *last_modified_time = base::Time::FromFileTime(file_time); | 139 return; |
140 } else { | |
141 last_modified_time_set = false; | |
142 } | |
143 } | 140 } |
144 return last_modified_time_set; | 141 |
| 142 SYSTEMTIME system_time; |
| 143 FILETIME file_time; |
| 144 if (last_modified_date.get().vt == VT_DATE && |
| 145 VariantTimeToSystemTime(last_modified_date.get().date, &system_time) && |
| 146 SystemTimeToFileTime(&system_time, &file_time)) { |
| 147 *last_modified_time = base::Time::FromFileTime(file_time); |
| 148 } |
145 } | 149 } |
146 | 150 |
147 // Gets the size of the file object in bytes from the property key values | 151 // Gets the size of the file object in bytes from the property key values |
148 // specified by the |properties_values|. On success, returns true and fills | 152 // specified by the |properties_values|. On success, returns true and fills |
149 // in |size|. | 153 // in |size|. |
150 bool GetObjectSize(IPortableDeviceValues* properties_values, int64* size) { | 154 bool GetObjectSize(IPortableDeviceValues* properties_values, int64* size) { |
151 DCHECK(properties_values); | 155 DCHECK(properties_values); |
152 DCHECK(size); | 156 DCHECK(size); |
153 ULONGLONG actual_size; | 157 ULONGLONG actual_size; |
154 HRESULT hr = properties_values->GetUnsignedLargeIntegerValue(WPD_OBJECT_SIZE, | 158 HRESULT hr = properties_values->GetUnsignedLargeIntegerValue(WPD_OBJECT_SIZE, |
155 &actual_size); | 159 &actual_size); |
156 bool success = SUCCEEDED(hr) && (actual_size <= kint64max); | 160 bool success = SUCCEEDED(hr) && (actual_size <= kint64max); |
157 if (success) | 161 if (success) |
158 *size = static_cast<int64>(actual_size); | 162 *size = static_cast<int64>(actual_size); |
159 return success; | 163 return success; |
160 } | 164 } |
161 | 165 |
162 // Gets the details of the object specified by the |object_id| given the media | 166 // Gets the details of the object specified by the |object_id| given the media |
163 // transfer protocol |device|. On success, returns true and fills in |name|, | 167 // transfer protocol |device|. On success, returns true and fills in |name|, |
164 // |is_directory|, |size| and |last_modified_time|. | 168 // |is_directory|, |size|. |last_modified_time| will be filled in if possible, |
| 169 // but failure to get it doesn't prevent success. |
165 bool GetObjectDetails(IPortableDevice* device, | 170 bool GetObjectDetails(IPortableDevice* device, |
166 const base::string16 object_id, | 171 const base::string16 object_id, |
167 base::string16* name, | 172 base::string16* name, |
168 bool* is_directory, | 173 bool* is_directory, |
169 int64* size, | 174 int64* size, |
170 base::Time* last_modified_time) { | 175 base::Time* last_modified_time) { |
171 base::ThreadRestrictions::AssertIOAllowed(); | 176 base::ThreadRestrictions::AssertIOAllowed(); |
172 DCHECK(device); | 177 DCHECK(device); |
173 DCHECK(!object_id.empty()); | 178 DCHECK(!object_id.empty()); |
174 DCHECK(name); | 179 DCHECK(name); |
(...skipping 15 matching lines...) Expand all Loading... |
190 NULL, | 195 NULL, |
191 CLSCTX_INPROC_SERVER); | 196 CLSCTX_INPROC_SERVER); |
192 if (FAILED(hr)) | 197 if (FAILED(hr)) |
193 return false; | 198 return false; |
194 | 199 |
195 if (FAILED(properties_to_read->Add(WPD_OBJECT_CONTENT_TYPE)) || | 200 if (FAILED(properties_to_read->Add(WPD_OBJECT_CONTENT_TYPE)) || |
196 FAILED(properties_to_read->Add(WPD_OBJECT_FORMAT)) || | 201 FAILED(properties_to_read->Add(WPD_OBJECT_FORMAT)) || |
197 FAILED(properties_to_read->Add(WPD_OBJECT_ORIGINAL_FILE_NAME)) || | 202 FAILED(properties_to_read->Add(WPD_OBJECT_ORIGINAL_FILE_NAME)) || |
198 FAILED(properties_to_read->Add(WPD_OBJECT_NAME)) || | 203 FAILED(properties_to_read->Add(WPD_OBJECT_NAME)) || |
199 FAILED(properties_to_read->Add(WPD_OBJECT_DATE_MODIFIED)) || | 204 FAILED(properties_to_read->Add(WPD_OBJECT_DATE_MODIFIED)) || |
| 205 FAILED(properties_to_read->Add(WPD_OBJECT_DATE_CREATED)) || |
200 FAILED(properties_to_read->Add(WPD_OBJECT_SIZE))) | 206 FAILED(properties_to_read->Add(WPD_OBJECT_SIZE))) |
201 return false; | 207 return false; |
202 | 208 |
203 base::win::ScopedComPtr<IPortableDeviceValues> properties_values; | 209 base::win::ScopedComPtr<IPortableDeviceValues> properties_values; |
204 hr = properties->GetValues(object_id.c_str(), | 210 hr = properties->GetValues(object_id.c_str(), |
205 properties_to_read.get(), | 211 properties_to_read.get(), |
206 properties_values.Receive()); | 212 properties_values.Receive()); |
207 if (FAILED(hr)) | 213 if (FAILED(hr)) |
208 return false; | 214 return false; |
209 | 215 |
210 *is_directory = IsDirectory(properties_values.get()); | 216 *is_directory = IsDirectory(properties_values.get()); |
211 *name = GetObjectName(properties_values.get()); | 217 *name = GetObjectName(properties_values.get()); |
212 if (name->empty()) | 218 if (name->empty()) |
213 return false; | 219 return false; |
214 | 220 |
215 if (*is_directory) { | 221 if (*is_directory) { |
216 // Directory entry does not have size and last modified date property key | 222 // Directory entry does not have size and last modified date property key |
217 // values. | 223 // values. |
218 *size = 0; | 224 *size = 0; |
219 *last_modified_time = base::Time(); | 225 *last_modified_time = base::Time(); |
220 return true; | 226 return true; |
221 } | 227 } |
222 return (GetObjectSize(properties_values.get(), size) && | 228 |
223 GetLastModifiedTime(properties_values.get(), last_modified_time)); | 229 // Try to get the last modified time, but don't fail if we can't. |
| 230 GetLastModifiedTime(properties_values.get(), last_modified_time); |
| 231 |
| 232 return GetObjectSize(properties_values.get(), size); |
224 } | 233 } |
225 | 234 |
226 // Creates an MTP device object entry for the given |device| and |object_id|. | 235 // Creates an MTP device object entry for the given |device| and |object_id|. |
227 // On success, returns true and fills in |entry|. | 236 // On success, returns true and fills in |entry|. |
228 bool GetMTPDeviceObjectEntry(IPortableDevice* device, | 237 bool GetMTPDeviceObjectEntry(IPortableDevice* device, |
229 const base::string16& object_id, | 238 const base::string16& object_id, |
230 MTPDeviceObjectEntry* entry) { | 239 MTPDeviceObjectEntry* entry) { |
231 base::ThreadRestrictions::AssertIOAllowed(); | 240 base::ThreadRestrictions::AssertIOAllowed(); |
232 DCHECK(device); | 241 DCHECK(device); |
233 DCHECK(!object_id.empty()); | 242 DCHECK(!object_id.empty()); |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 object_entries.empty()) | 408 object_entries.empty()) |
400 return base::string16(); | 409 return base::string16(); |
401 // TODO(thestig): This DCHECK can fail. Multiple MTP objects can have | 410 // TODO(thestig): This DCHECK can fail. Multiple MTP objects can have |
402 // the same name. Handle the situation gracefully. Refer to crbug.com/169930 | 411 // the same name. Handle the situation gracefully. Refer to crbug.com/169930 |
403 // for more details. | 412 // for more details. |
404 DCHECK_EQ(1U, object_entries.size()); | 413 DCHECK_EQ(1U, object_entries.size()); |
405 return object_entries[0].object_id; | 414 return object_entries[0].object_id; |
406 } | 415 } |
407 | 416 |
408 } // namespace media_transfer_protocol | 417 } // namespace media_transfer_protocol |
OLD | NEW |