| 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 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 return true; | 52 return true; |
| 53 } | 53 } |
| 54 | 54 |
| 55 // Gets the content interface of the portable |device|. On success, returns | 55 // Gets the content interface of the portable |device|. On success, returns |
| 56 // the IPortableDeviceContent interface. On failure, returns NULL. | 56 // the IPortableDeviceContent interface. On failure, returns NULL. |
| 57 base::win::ScopedComPtr<IPortableDeviceContent> GetDeviceContent( | 57 base::win::ScopedComPtr<IPortableDeviceContent> GetDeviceContent( |
| 58 IPortableDevice* device) { | 58 IPortableDevice* device) { |
| 59 base::ThreadRestrictions::AssertIOAllowed(); | 59 base::ThreadRestrictions::AssertIOAllowed(); |
| 60 DCHECK(device); | 60 DCHECK(device); |
| 61 base::win::ScopedComPtr<IPortableDeviceContent> content; | 61 base::win::ScopedComPtr<IPortableDeviceContent> content; |
| 62 if (SUCCEEDED(device->Content(content.Receive()))) | 62 if (SUCCEEDED(device->Content(content.GetAddressOf()))) |
| 63 return content; | 63 return content; |
| 64 return base::win::ScopedComPtr<IPortableDeviceContent>(); | 64 return base::win::ScopedComPtr<IPortableDeviceContent>(); |
| 65 } | 65 } |
| 66 | 66 |
| 67 // On success, returns IEnumPortableDeviceObjectIDs interface to enumerate | 67 // On success, returns IEnumPortableDeviceObjectIDs interface to enumerate |
| 68 // the device objects. On failure, returns NULL. | 68 // the device objects. On failure, returns NULL. |
| 69 // |parent_id| specifies the parent object identifier. | 69 // |parent_id| specifies the parent object identifier. |
| 70 base::win::ScopedComPtr<IEnumPortableDeviceObjectIDs> GetDeviceObjectEnumerator( | 70 base::win::ScopedComPtr<IEnumPortableDeviceObjectIDs> GetDeviceObjectEnumerator( |
| 71 IPortableDevice* device, | 71 IPortableDevice* device, |
| 72 const base::string16& parent_id) { | 72 const base::string16& parent_id) { |
| 73 base::ThreadRestrictions::AssertIOAllowed(); | 73 base::ThreadRestrictions::AssertIOAllowed(); |
| 74 DCHECK(device); | 74 DCHECK(device); |
| 75 DCHECK(!parent_id.empty()); | 75 DCHECK(!parent_id.empty()); |
| 76 base::win::ScopedComPtr<IPortableDeviceContent> content = | 76 base::win::ScopedComPtr<IPortableDeviceContent> content = |
| 77 GetDeviceContent(device); | 77 GetDeviceContent(device); |
| 78 if (!content.Get()) | 78 if (!content.Get()) |
| 79 return base::win::ScopedComPtr<IEnumPortableDeviceObjectIDs>(); | 79 return base::win::ScopedComPtr<IEnumPortableDeviceObjectIDs>(); |
| 80 | 80 |
| 81 base::win::ScopedComPtr<IEnumPortableDeviceObjectIDs> enum_object_ids; | 81 base::win::ScopedComPtr<IEnumPortableDeviceObjectIDs> enum_object_ids; |
| 82 if (SUCCEEDED(content->EnumObjects(0, parent_id.c_str(), NULL, | 82 if (SUCCEEDED(content->EnumObjects(0, parent_id.c_str(), NULL, |
| 83 enum_object_ids.Receive()))) | 83 enum_object_ids.GetAddressOf()))) |
| 84 return enum_object_ids; | 84 return enum_object_ids; |
| 85 return base::win::ScopedComPtr<IEnumPortableDeviceObjectIDs>(); | 85 return base::win::ScopedComPtr<IEnumPortableDeviceObjectIDs>(); |
| 86 } | 86 } |
| 87 | 87 |
| 88 // Returns whether the object is a directory/folder/album. |properties_values| | 88 // Returns whether the object is a directory/folder/album. |properties_values| |
| 89 // contains the object property key values. | 89 // contains the object property key values. |
| 90 bool IsDirectory(IPortableDeviceValues* properties_values) { | 90 bool IsDirectory(IPortableDeviceValues* properties_values) { |
| 91 DCHECK(properties_values); | 91 DCHECK(properties_values); |
| 92 GUID content_type; | 92 GUID content_type; |
| 93 HRESULT hr = properties_values->GetGuidValue(WPD_OBJECT_CONTENT_TYPE, | 93 HRESULT hr = properties_values->GetGuidValue(WPD_OBJECT_CONTENT_TYPE, |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 DCHECK(name); | 179 DCHECK(name); |
| 180 DCHECK(is_directory); | 180 DCHECK(is_directory); |
| 181 DCHECK(size); | 181 DCHECK(size); |
| 182 DCHECK(last_modified_time); | 182 DCHECK(last_modified_time); |
| 183 base::win::ScopedComPtr<IPortableDeviceContent> content = | 183 base::win::ScopedComPtr<IPortableDeviceContent> content = |
| 184 GetDeviceContent(device); | 184 GetDeviceContent(device); |
| 185 if (!content.Get()) | 185 if (!content.Get()) |
| 186 return false; | 186 return false; |
| 187 | 187 |
| 188 base::win::ScopedComPtr<IPortableDeviceProperties> properties; | 188 base::win::ScopedComPtr<IPortableDeviceProperties> properties; |
| 189 HRESULT hr = content->Properties(properties.Receive()); | 189 HRESULT hr = content->Properties(properties.GetAddressOf()); |
| 190 if (FAILED(hr)) | 190 if (FAILED(hr)) |
| 191 return false; | 191 return false; |
| 192 | 192 |
| 193 base::win::ScopedComPtr<IPortableDeviceKeyCollection> properties_to_read; | 193 base::win::ScopedComPtr<IPortableDeviceKeyCollection> properties_to_read; |
| 194 hr = properties_to_read.CreateInstance(__uuidof(PortableDeviceKeyCollection), | 194 hr = properties_to_read.CreateInstance(__uuidof(PortableDeviceKeyCollection), |
| 195 NULL, | 195 NULL, |
| 196 CLSCTX_INPROC_SERVER); | 196 CLSCTX_INPROC_SERVER); |
| 197 if (FAILED(hr)) | 197 if (FAILED(hr)) |
| 198 return false; | 198 return false; |
| 199 | 199 |
| 200 if (FAILED(properties_to_read->Add(WPD_OBJECT_CONTENT_TYPE)) || | 200 if (FAILED(properties_to_read->Add(WPD_OBJECT_CONTENT_TYPE)) || |
| 201 FAILED(properties_to_read->Add(WPD_OBJECT_FORMAT)) || | 201 FAILED(properties_to_read->Add(WPD_OBJECT_FORMAT)) || |
| 202 FAILED(properties_to_read->Add(WPD_OBJECT_ORIGINAL_FILE_NAME)) || | 202 FAILED(properties_to_read->Add(WPD_OBJECT_ORIGINAL_FILE_NAME)) || |
| 203 FAILED(properties_to_read->Add(WPD_OBJECT_NAME)) || | 203 FAILED(properties_to_read->Add(WPD_OBJECT_NAME)) || |
| 204 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)) || | 205 FAILED(properties_to_read->Add(WPD_OBJECT_DATE_CREATED)) || |
| 206 FAILED(properties_to_read->Add(WPD_OBJECT_SIZE))) | 206 FAILED(properties_to_read->Add(WPD_OBJECT_SIZE))) |
| 207 return false; | 207 return false; |
| 208 | 208 |
| 209 base::win::ScopedComPtr<IPortableDeviceValues> properties_values; | 209 base::win::ScopedComPtr<IPortableDeviceValues> properties_values; |
| 210 hr = properties->GetValues(object_id.c_str(), | 210 hr = properties->GetValues(object_id.c_str(), properties_to_read.Get(), |
| 211 properties_to_read.Get(), | 211 properties_values.GetAddressOf()); |
| 212 properties_values.Receive()); | |
| 213 if (FAILED(hr)) | 212 if (FAILED(hr)) |
| 214 return false; | 213 return false; |
| 215 | 214 |
| 216 *is_directory = IsDirectory(properties_values.Get()); | 215 *is_directory = IsDirectory(properties_values.Get()); |
| 217 *name = GetObjectName(properties_values.Get()); | 216 *name = GetObjectName(properties_values.Get()); |
| 218 if (name->empty()) | 217 if (name->empty()) |
| 219 return false; | 218 return false; |
| 220 | 219 |
| 221 if (*is_directory) { | 220 if (*is_directory) { |
| 222 // Directory entry does not have size and last modified date property key | 221 // Directory entry does not have size and last modified date property key |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 DWORD* optimal_transfer_size) { | 356 DWORD* optimal_transfer_size) { |
| 358 base::ThreadRestrictions::AssertIOAllowed(); | 357 base::ThreadRestrictions::AssertIOAllowed(); |
| 359 DCHECK(device); | 358 DCHECK(device); |
| 360 DCHECK(!file_object_id.empty()); | 359 DCHECK(!file_object_id.empty()); |
| 361 base::win::ScopedComPtr<IPortableDeviceContent> content = | 360 base::win::ScopedComPtr<IPortableDeviceContent> content = |
| 362 GetDeviceContent(device); | 361 GetDeviceContent(device); |
| 363 if (!content.Get()) | 362 if (!content.Get()) |
| 364 return E_FAIL; | 363 return E_FAIL; |
| 365 | 364 |
| 366 base::win::ScopedComPtr<IPortableDeviceResources> resources; | 365 base::win::ScopedComPtr<IPortableDeviceResources> resources; |
| 367 HRESULT hr = content->Transfer(resources.Receive()); | 366 HRESULT hr = content->Transfer(resources.GetAddressOf()); |
| 368 if (FAILED(hr)) | 367 if (FAILED(hr)) |
| 369 return hr; | 368 return hr; |
| 370 return resources->GetStream(file_object_id.c_str(), WPD_RESOURCE_DEFAULT, | 369 return resources->GetStream(file_object_id.c_str(), WPD_RESOURCE_DEFAULT, |
| 371 STGM_READ, optimal_transfer_size, | 370 STGM_READ, optimal_transfer_size, |
| 372 file_stream); | 371 file_stream); |
| 373 } | 372 } |
| 374 | 373 |
| 375 DWORD CopyDataChunkToLocalFile(IStream* stream, | 374 DWORD CopyDataChunkToLocalFile(IStream* stream, |
| 376 const base::FilePath& local_path, | 375 const base::FilePath& local_path, |
| 377 size_t optimal_transfer_size) { | 376 size_t optimal_transfer_size) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 object_entries.empty()) | 408 object_entries.empty()) |
| 410 return base::string16(); | 409 return base::string16(); |
| 411 // TODO(thestig): This DCHECK can fail. Multiple MTP objects can have | 410 // TODO(thestig): This DCHECK can fail. Multiple MTP objects can have |
| 412 // 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 |
| 413 // for more details. | 412 // for more details. |
| 414 DCHECK_EQ(1U, object_entries.size()); | 413 DCHECK_EQ(1U, object_entries.size()); |
| 415 return object_entries[0].object_id; | 414 return object_entries[0].object_id; |
| 416 } | 415 } |
| 417 | 416 |
| 418 } // namespace media_transfer_protocol | 417 } // namespace media_transfer_protocol |
| OLD | NEW |