| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 // Any tasks that communicates with the portable device may take >100ms to | 5 // Any tasks that communicates with the portable device may take >100ms to |
| 6 // complete. Those tasks should be run on an blocking thread instead of the | 6 // complete. Those tasks should be run on an blocking thread instead of the |
| 7 // UI thread. | 7 // UI thread. |
| 8 | 8 |
| 9 #include "components/storage_monitor/portable_device_watcher_win.h" | 9 #include "components/storage_monitor/portable_device_watcher_win.h" |
| 10 | 10 |
| 11 #include <dbt.h> | 11 #include <dbt.h> |
| 12 #include <objbase.h> |
| 12 #include <portabledevice.h> | 13 #include <portabledevice.h> |
| 13 | 14 |
| 14 #include "base/files/file_path.h" | 15 #include "base/files/file_path.h" |
| 15 #include "base/logging.h" | 16 #include "base/logging.h" |
| 16 #include "base/stl_util.h" | 17 #include "base/stl_util.h" |
| 17 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| 18 #include "base/strings/utf_string_conversions.h" | 19 #include "base/strings/utf_string_conversions.h" |
| 19 #include "base/threading/sequenced_worker_pool.h" | 20 #include "base/threading/sequenced_worker_pool.h" |
| 20 #include "base/win/scoped_co_mem.h" | 21 #include "base/win/scoped_co_mem.h" |
| 21 #include "base/win/scoped_comptr.h" | 22 #include "base/win/scoped_comptr.h" |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 115 hr = device_manager->GetDeviceDescription( | 116 hr = device_manager->GetDeviceDescription( |
| 116 pnp_device_id.c_str(), base::WriteInto(description, desc_len), &desc_len); | 117 pnp_device_id.c_str(), base::WriteInto(description, desc_len), &desc_len); |
| 117 return (SUCCEEDED(hr) && !description->empty()); | 118 return (SUCCEEDED(hr) && !description->empty()); |
| 118 } | 119 } |
| 119 | 120 |
| 120 // On success, returns true and updates |client_info| with a reference to an | 121 // On success, returns true and updates |client_info| with a reference to an |
| 121 // IPortableDeviceValues interface that holds information about the | 122 // IPortableDeviceValues interface that holds information about the |
| 122 // application that communicates with the device. | 123 // application that communicates with the device. |
| 123 bool GetClientInformation( | 124 bool GetClientInformation( |
| 124 base::win::ScopedComPtr<IPortableDeviceValues>* client_info) { | 125 base::win::ScopedComPtr<IPortableDeviceValues>* client_info) { |
| 125 HRESULT hr = client_info->CreateInstance(__uuidof(PortableDeviceValues), | 126 HRESULT hr = ::CoCreateInstance(__uuidof(PortableDeviceValues), NULL, |
| 126 NULL, CLSCTX_INPROC_SERVER); | 127 CLSCTX_INPROC_SERVER, |
| 128 IID_PPV_ARGS(client_info->GetAddressOf())); |
| 127 if (FAILED(hr)) { | 129 if (FAILED(hr)) { |
| 128 DPLOG(ERROR) << "Failed to create an instance of IPortableDeviceValues"; | 130 DPLOG(ERROR) << "Failed to create an instance of IPortableDeviceValues"; |
| 129 return false; | 131 return false; |
| 130 } | 132 } |
| 131 | 133 |
| 132 // Attempt to set client details. | 134 // Attempt to set client details. |
| 133 (*client_info)->SetStringValue(WPD_CLIENT_NAME, kClientName); | 135 (*client_info)->SetStringValue(WPD_CLIENT_NAME, kClientName); |
| 134 (*client_info)->SetUnsignedIntegerValue(WPD_CLIENT_MAJOR_VERSION, 0); | 136 (*client_info)->SetUnsignedIntegerValue(WPD_CLIENT_MAJOR_VERSION, 0); |
| 135 (*client_info)->SetUnsignedIntegerValue(WPD_CLIENT_MINOR_VERSION, 0); | 137 (*client_info)->SetUnsignedIntegerValue(WPD_CLIENT_MINOR_VERSION, 0); |
| 136 (*client_info)->SetUnsignedIntegerValue(WPD_CLIENT_REVISION, 0); | 138 (*client_info)->SetUnsignedIntegerValue(WPD_CLIENT_REVISION, 0); |
| 137 (*client_info)->SetUnsignedIntegerValue( | 139 (*client_info)->SetUnsignedIntegerValue( |
| 138 WPD_CLIENT_SECURITY_QUALITY_OF_SERVICE, SECURITY_IMPERSONATION); | 140 WPD_CLIENT_SECURITY_QUALITY_OF_SERVICE, SECURITY_IMPERSONATION); |
| 139 (*client_info)->SetUnsignedIntegerValue(WPD_CLIENT_DESIRED_ACCESS, | 141 (*client_info)->SetUnsignedIntegerValue(WPD_CLIENT_DESIRED_ACCESS, |
| 140 GENERIC_READ); | 142 GENERIC_READ); |
| 141 return true; | 143 return true; |
| 142 } | 144 } |
| 143 | 145 |
| 144 // Opens the device for communication. |pnp_device_id| specifies the plug and | 146 // Opens the device for communication. |pnp_device_id| specifies the plug and |
| 145 // play device ID string. On success, returns true and updates |device| with a | 147 // play device ID string. On success, returns true and updates |device| with a |
| 146 // reference to the portable device interface. | 148 // reference to the portable device interface. |
| 147 bool SetUp(const base::string16& pnp_device_id, | 149 bool SetUp(const base::string16& pnp_device_id, |
| 148 base::win::ScopedComPtr<IPortableDevice>* device) { | 150 base::win::ScopedComPtr<IPortableDevice>* device) { |
| 149 base::win::ScopedComPtr<IPortableDeviceValues> client_info; | 151 base::win::ScopedComPtr<IPortableDeviceValues> client_info; |
| 150 if (!GetClientInformation(&client_info)) | 152 if (!GetClientInformation(&client_info)) |
| 151 return false; | 153 return false; |
| 152 | 154 |
| 153 HRESULT hr = device->CreateInstance(__uuidof(PortableDevice), NULL, | 155 HRESULT hr = |
| 154 CLSCTX_INPROC_SERVER); | 156 ::CoCreateInstance(__uuidof(PortableDevice), NULL, CLSCTX_INPROC_SERVER, |
| 157 IID_PPV_ARGS(device->GetAddressOf())); |
| 155 if (FAILED(hr)) { | 158 if (FAILED(hr)) { |
| 156 DPLOG(ERROR) << "Failed to create an instance of IPortableDevice"; | 159 DPLOG(ERROR) << "Failed to create an instance of IPortableDevice"; |
| 157 return false; | 160 return false; |
| 158 } | 161 } |
| 159 | 162 |
| 160 hr = (*device)->Open(pnp_device_id.c_str(), client_info.Get()); | 163 hr = (*device)->Open(pnp_device_id.c_str(), client_info.Get()); |
| 161 if (SUCCEEDED(hr)) | 164 if (SUCCEEDED(hr)) |
| 162 return true; | 165 return true; |
| 163 | 166 |
| 164 if (hr == E_ACCESSDENIED) | 167 if (hr == E_ACCESSDENIED) |
| 165 DPLOG(ERROR) << "Access denied to open the device"; | 168 DPLOG(ERROR) << "Access denied to open the device"; |
| 166 return false; | 169 return false; |
| 167 } | 170 } |
| 168 | 171 |
| 169 // Returns the unique id property key of the object specified by the | 172 // Returns the unique id property key of the object specified by the |
| 170 // |object_id|. | 173 // |object_id|. |
| 171 REFPROPERTYKEY GetUniqueIdPropertyKey(const base::string16& object_id) { | 174 REFPROPERTYKEY GetUniqueIdPropertyKey(const base::string16& object_id) { |
| 172 return (object_id == WPD_DEVICE_OBJECT_ID) ? | 175 return (object_id == WPD_DEVICE_OBJECT_ID) ? |
| 173 WPD_DEVICE_SERIAL_NUMBER : WPD_OBJECT_PERSISTENT_UNIQUE_ID; | 176 WPD_DEVICE_SERIAL_NUMBER : WPD_OBJECT_PERSISTENT_UNIQUE_ID; |
| 174 } | 177 } |
| 175 | 178 |
| 176 // On success, returns true and populates |properties_to_read| with the | 179 // On success, returns true and populates |properties_to_read| with the |
| 177 // property key of the object specified by the |object_id|. | 180 // property key of the object specified by the |object_id|. |
| 178 bool PopulatePropertyKeyCollection( | 181 bool PopulatePropertyKeyCollection( |
| 179 const base::string16& object_id, | 182 const base::string16& object_id, |
| 180 base::win::ScopedComPtr<IPortableDeviceKeyCollection>* properties_to_read) { | 183 base::win::ScopedComPtr<IPortableDeviceKeyCollection>* properties_to_read) { |
| 181 HRESULT hr = properties_to_read->CreateInstance( | 184 HRESULT hr = ::CoCreateInstance( |
| 182 __uuidof(PortableDeviceKeyCollection), NULL, CLSCTX_INPROC_SERVER); | 185 __uuidof(PortableDeviceKeyCollection), NULL, CLSCTX_INPROC_SERVER, |
| 186 IID_PPV_ARGS(properties_to_read->GetAddressOf())); |
| 183 if (FAILED(hr)) { | 187 if (FAILED(hr)) { |
| 184 DPLOG(ERROR) << "Failed to create IPortableDeviceKeyCollection instance"; | 188 DPLOG(ERROR) << "Failed to create IPortableDeviceKeyCollection instance"; |
| 185 return false; | 189 return false; |
| 186 } | 190 } |
| 187 REFPROPERTYKEY key = GetUniqueIdPropertyKey(object_id); | 191 REFPROPERTYKEY key = GetUniqueIdPropertyKey(object_id); |
| 188 hr = (*properties_to_read)->Add(key); | 192 hr = (*properties_to_read)->Add(key); |
| 189 return SUCCEEDED(hr); | 193 return SUCCEEDED(hr); |
| 190 } | 194 } |
| 191 | 195 |
| 192 // Wrapper function to get content property string value. | 196 // Wrapper function to get content property string value. |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 PortableDeviceWatcherWin::StorageObjects storage_objects; | 382 PortableDeviceWatcherWin::StorageObjects storage_objects; |
| 379 return GetDeviceStorageObjectsOnBlockingThread( | 383 return GetDeviceStorageObjectsOnBlockingThread( |
| 380 pnp_device_id, &device_details->storage_objects); | 384 pnp_device_id, &device_details->storage_objects); |
| 381 } | 385 } |
| 382 | 386 |
| 383 // Wrapper function to get an instance of portable device manager. On success, | 387 // Wrapper function to get an instance of portable device manager. On success, |
| 384 // returns true and fills in |portable_device_mgr|. On failure, returns false. | 388 // returns true and fills in |portable_device_mgr|. On failure, returns false. |
| 385 bool GetPortableDeviceManager( | 389 bool GetPortableDeviceManager( |
| 386 base::win::ScopedComPtr<IPortableDeviceManager>* portable_device_mgr) { | 390 base::win::ScopedComPtr<IPortableDeviceManager>* portable_device_mgr) { |
| 387 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); | 391 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); |
| 388 HRESULT hr = portable_device_mgr->CreateInstance( | 392 HRESULT hr = ::CoCreateInstance( |
| 389 __uuidof(PortableDeviceManager), NULL, CLSCTX_INPROC_SERVER); | 393 __uuidof(PortableDeviceManager), NULL, CLSCTX_INPROC_SERVER, |
| 394 IID_PPV_ARGS(portable_device_mgr->GetAddressOf())); |
| 390 if (SUCCEEDED(hr)) | 395 if (SUCCEEDED(hr)) |
| 391 return true; | 396 return true; |
| 392 | 397 |
| 393 // Either there is no portable device support (Windows XP with old versions of | 398 // Either there is no portable device support (Windows XP with old versions of |
| 394 // Media Player) or the thread does not have COM initialized. | 399 // Media Player) or the thread does not have COM initialized. |
| 395 DCHECK_NE(CO_E_NOTINITIALIZED, hr); | 400 DCHECK_NE(CO_E_NOTINITIALIZED, hr); |
| 396 return false; | 401 return false; |
| 397 } | 402 } |
| 398 | 403 |
| 399 // Enumerates the attached portable devices. On success, returns true and fills | 404 // Enumerates the attached portable devices. On success, returns true and fills |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 665 if (storage_notifications_) { | 670 if (storage_notifications_) { |
| 666 storage_notifications_->ProcessDetach( | 671 storage_notifications_->ProcessDetach( |
| 667 storage_map_iter->second.device_id()); | 672 storage_map_iter->second.device_id()); |
| 668 } | 673 } |
| 669 storage_map_.erase(storage_map_iter); | 674 storage_map_.erase(storage_map_iter); |
| 670 } | 675 } |
| 671 device_map_.erase(device_iter); | 676 device_map_.erase(device_iter); |
| 672 } | 677 } |
| 673 | 678 |
| 674 } // namespace storage_monitor | 679 } // namespace storage_monitor |
| OLD | NEW |