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 |