OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "device/devices_app/usb/device_manager_impl.h" | 5 #include "device/devices_app/usb/device_manager_impl.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/location.h" | 8 #include "base/location.h" |
9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
11 #include "base/scoped_observer.h" | 11 #include "base/scoped_observer.h" |
12 #include "base/sequenced_task_runner.h" | 12 #include "base/sequenced_task_runner.h" |
13 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
14 #include "base/thread_task_runner_handle.h" | 14 #include "base/thread_task_runner_handle.h" |
15 #include "device/core/device_client.h" | 15 #include "device/core/device_client.h" |
16 #include "device/devices_app/usb/device_impl.h" | 16 #include "device/devices_app/usb/device_impl.h" |
17 #include "device/devices_app/usb/public/cpp/device_manager_delegate.h" | |
18 #include "device/devices_app/usb/public/interfaces/device.mojom.h" | 17 #include "device/devices_app/usb/public/interfaces/device.mojom.h" |
19 #include "device/devices_app/usb/type_converters.h" | 18 #include "device/devices_app/usb/type_converters.h" |
20 #include "device/usb/usb_device.h" | 19 #include "device/usb/usb_device.h" |
21 #include "device/usb/usb_device_filter.h" | 20 #include "device/usb/usb_device_filter.h" |
22 #include "device/usb/usb_service.h" | 21 #include "device/usb/usb_service.h" |
23 #include "third_party/mojo/src/mojo/public/cpp/bindings/array.h" | 22 #include "third_party/mojo/src/mojo/public/cpp/bindings/array.h" |
24 #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" | 23 #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" |
25 | 24 |
26 namespace device { | 25 namespace device { |
27 namespace usb { | 26 namespace usb { |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
101 callback_task_runner->PostTask(FROM_HERE, | 100 callback_task_runner->PostTask(FROM_HERE, |
102 base::Bind(&RunOpenDeviceCallback, callback, | 101 base::Bind(&RunOpenDeviceCallback, callback, |
103 OPEN_DEVICE_ERROR_NOT_FOUND)); | 102 OPEN_DEVICE_ERROR_NOT_FOUND)); |
104 return; | 103 return; |
105 } | 104 } |
106 device->Open(base::Bind(&OnOpenDeviceOnServiceThread, | 105 device->Open(base::Bind(&OnOpenDeviceOnServiceThread, |
107 base::Passed(&device_request), callback, | 106 base::Passed(&device_request), callback, |
108 callback_task_runner)); | 107 callback_task_runner)); |
109 } | 108 } |
110 | 109 |
110 void FilterDeviceListAndThen( | |
111 const DeviceManagerImpl::GetDevicesCallback& callback, | |
112 mojo::Array<DeviceInfoPtr> devices, | |
113 mojo::Array<mojo::String> allowed_guids) { | |
114 std::set<std::string> allowed_guid_set; | |
115 for (size_t i = 0; i < allowed_guids.size(); ++i) | |
116 allowed_guid_set.insert(allowed_guids[i]); | |
117 | |
118 mojo::Array<DeviceInfoPtr> allowed_devices(0); | |
119 for (size_t i = 0; i < devices.size(); ++i) { | |
120 if (ContainsKey(allowed_guid_set, devices[i]->guid)) | |
121 allowed_devices.push_back(devices[i].Pass()); | |
122 } | |
123 | |
124 callback.Run(allowed_devices.Pass()); | |
125 } | |
126 | |
111 } // namespace | 127 } // namespace |
112 | 128 |
113 class DeviceManagerImpl::ServiceThreadHelper | 129 class DeviceManagerImpl::ServiceThreadHelper |
114 : public UsbService::Observer, | 130 : public UsbService::Observer, |
115 public base::MessageLoop::DestructionObserver { | 131 public base::MessageLoop::DestructionObserver { |
116 public: | 132 public: |
117 ServiceThreadHelper(base::WeakPtr<DeviceManagerImpl> manager, | 133 ServiceThreadHelper(base::WeakPtr<DeviceManagerImpl> manager, |
118 scoped_refptr<base::TaskRunner> task_runner) | 134 scoped_refptr<base::TaskRunner> task_runner) |
119 : observer_(this), manager_(manager), task_runner_(task_runner) {} | 135 : observer_(this), manager_(manager), task_runner_(task_runner) {} |
120 | 136 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
156 // base::MessageLoop::DestructionObserver | 172 // base::MessageLoop::DestructionObserver |
157 void WillDestroyCurrentMessageLoop() override { delete this; } | 173 void WillDestroyCurrentMessageLoop() override { delete this; } |
158 | 174 |
159 ScopedObserver<UsbService, UsbService::Observer> observer_; | 175 ScopedObserver<UsbService, UsbService::Observer> observer_; |
160 base::WeakPtr<DeviceManagerImpl> manager_; | 176 base::WeakPtr<DeviceManagerImpl> manager_; |
161 scoped_refptr<base::TaskRunner> task_runner_; | 177 scoped_refptr<base::TaskRunner> task_runner_; |
162 }; | 178 }; |
163 | 179 |
164 DeviceManagerImpl::DeviceManagerImpl( | 180 DeviceManagerImpl::DeviceManagerImpl( |
165 mojo::InterfaceRequest<DeviceManager> request, | 181 mojo::InterfaceRequest<DeviceManager> request, |
166 scoped_ptr<DeviceManagerDelegate> delegate, | 182 PermissionProviderPtr permission_provider, |
167 scoped_refptr<base::SequencedTaskRunner> service_task_runner) | 183 scoped_refptr<base::SequencedTaskRunner> service_task_runner) |
168 : binding_(this, request.Pass()), | 184 : binding_(this, request.Pass()), |
169 delegate_(delegate.Pass()), | 185 permission_provider_(permission_provider.Pass()), |
170 service_task_runner_(service_task_runner), | 186 service_task_runner_(service_task_runner), |
171 weak_factory_(this) { | 187 weak_factory_(this) {} |
172 } | |
173 | 188 |
174 DeviceManagerImpl::~DeviceManagerImpl() { | 189 DeviceManagerImpl::~DeviceManagerImpl() { |
Ken Rockot(use gerrit already)
2015/09/02 22:42:33
nit: I totally missed this before, but could you p
Reilly Grant (use Gerrit)
2015/09/02 23:58:18
Done.
| |
175 if (helper_) { | 190 if (helper_) { |
176 // It is safe to call this if |helper_| was already destroyed when | 191 // It is safe to call this if |helper_| was already destroyed when |
177 // |service_task_runner_| exited as the task will never execute. | 192 // |service_task_runner_| exited as the task will never execute. |
178 service_task_runner_->DeleteSoon(FROM_HERE, helper_); | 193 service_task_runner_->DeleteSoon(FROM_HERE, helper_); |
179 } | 194 } |
180 } | 195 } |
181 | 196 |
182 void DeviceManagerImpl::set_connection_error_handler( | 197 void DeviceManagerImpl::set_connection_error_handler( |
183 const mojo::Closure& error_handler) { | 198 const mojo::Closure& error_handler) { |
184 binding_.set_connection_error_handler(error_handler); | 199 binding_.set_connection_error_handler(error_handler); |
185 } | 200 } |
186 | 201 |
187 void DeviceManagerImpl::GetDevices(EnumerationOptionsPtr options, | 202 void DeviceManagerImpl::GetDevices(EnumerationOptionsPtr options, |
188 const GetDevicesCallback& callback) { | 203 const GetDevicesCallback& callback) { |
189 auto filters = options->filters.To<std::vector<UsbDeviceFilter>>(); | 204 auto filters = options->filters.To<std::vector<UsbDeviceFilter>>(); |
190 auto get_devices_callback = base::Bind(&DeviceManagerImpl::OnGetDevices, | 205 auto get_devices_callback = base::Bind(&DeviceManagerImpl::OnGetDevices, |
191 weak_factory_.GetWeakPtr(), callback); | 206 weak_factory_.GetWeakPtr(), callback); |
192 service_task_runner_->PostTask( | 207 service_task_runner_->PostTask( |
193 FROM_HERE, | 208 FROM_HERE, |
194 base::Bind(&GetDevicesOnServiceThread, filters, get_devices_callback, | 209 base::Bind(&GetDevicesOnServiceThread, filters, get_devices_callback, |
195 base::ThreadTaskRunnerHandle::Get())); | 210 base::ThreadTaskRunnerHandle::Get())); |
196 } | 211 } |
197 | 212 |
198 void DeviceManagerImpl::GetDeviceChanges( | 213 void DeviceManagerImpl::GetDeviceChanges( |
199 const GetDeviceChangesCallback& callback) { | 214 const GetDeviceChangesCallback& callback) { |
215 device_change_callbacks_.push(callback); | |
200 if (helper_) { | 216 if (helper_) { |
201 device_change_callbacks_.push(callback); | |
202 MaybeRunDeviceChangesCallback(); | 217 MaybeRunDeviceChangesCallback(); |
203 } else { | 218 } else { |
204 scoped_ptr<ServiceThreadHelper> helper(new ServiceThreadHelper( | 219 scoped_ptr<ServiceThreadHelper> helper(new ServiceThreadHelper( |
205 weak_factory_.GetWeakPtr(), base::ThreadTaskRunnerHandle::Get())); | 220 weak_factory_.GetWeakPtr(), base::ThreadTaskRunnerHandle::Get())); |
206 helper_ = helper.get(); | 221 helper_ = helper.get(); |
207 auto get_devices_callback = | |
208 base::Bind(&DeviceManagerImpl::OnGetInitialDevices, | |
209 weak_factory_.GetWeakPtr(), callback); | |
210 service_task_runner_->PostTask( | 222 service_task_runner_->PostTask( |
211 FROM_HERE, base::Bind(&ServiceThreadHelper::Start, | 223 FROM_HERE, |
212 base::Passed(&helper), get_devices_callback)); | 224 base::Bind(&ServiceThreadHelper::Start, base::Passed(&helper), |
225 base::Bind(&DeviceManagerImpl::OnGetInitialDevices, | |
226 weak_factory_.GetWeakPtr()))); | |
213 } | 227 } |
214 } | 228 } |
215 | 229 |
216 void DeviceManagerImpl::OpenDevice( | 230 void DeviceManagerImpl::OpenDevice( |
217 const mojo::String& guid, | 231 const mojo::String& guid, |
218 mojo::InterfaceRequest<Device> device_request, | 232 mojo::InterfaceRequest<Device> device_request, |
219 const OpenDeviceCallback& callback) { | 233 const OpenDeviceCallback& callback) { |
220 service_task_runner_->PostTask( | 234 service_task_runner_->PostTask( |
221 FROM_HERE, base::Bind(&OpenDeviceOnServiceThread, guid, | 235 FROM_HERE, base::Bind(&OpenDeviceOnServiceThread, guid, |
222 base::Passed(&device_request), callback, | 236 base::Passed(&device_request), callback, |
223 base::ThreadTaskRunnerHandle::Get())); | 237 base::ThreadTaskRunnerHandle::Get())); |
224 } | 238 } |
225 | 239 |
226 void DeviceManagerImpl::OnGetDevices(const GetDevicesCallback& callback, | 240 void DeviceManagerImpl::OnGetDevices(const GetDevicesCallback& callback, |
227 mojo::Array<DeviceInfoPtr> devices) { | 241 mojo::Array<DeviceInfoPtr> devices) { |
228 mojo::Array<DeviceInfoPtr> allowed_devices(0); | 242 mojo::Array<mojo::String> requested_guids(devices.size()); |
229 for (size_t i = 0; i < devices.size(); ++i) { | 243 for (size_t i = 0; i < devices.size(); ++i) { |
230 if (delegate_->IsDeviceAllowed(*devices[i])) | 244 requested_guids[i] = devices[i]->guid; |
231 allowed_devices.push_back(devices[i].Pass()); | |
232 } | 245 } |
233 callback.Run(allowed_devices.Pass()); | 246 permission_provider_->HasDevicePermission( |
247 requested_guids.Pass(), | |
248 base::Bind(&FilterDeviceListAndThen, callback, base::Passed(&devices))); | |
234 } | 249 } |
235 | 250 |
236 void DeviceManagerImpl::OnGetInitialDevices( | 251 void DeviceManagerImpl::OnGetInitialDevices( |
237 const GetDeviceChangesCallback& callback, | |
238 mojo::Array<DeviceInfoPtr> devices) { | 252 mojo::Array<DeviceInfoPtr> devices) { |
239 DeviceChangeNotificationPtr notification = DeviceChangeNotification::New(); | 253 DCHECK_EQ(0u, devices_added_.size()); |
240 notification->devices_added = mojo::Array<DeviceInfoPtr>::New(0); | 254 DCHECK(devices_removed_.empty()); |
241 notification->devices_removed = mojo::Array<mojo::String>::New(0); | 255 devices_added_.Swap(&devices); |
242 for (size_t i = 0; i < devices.size(); ++i) { | 256 MaybeRunDeviceChangesCallback(); |
243 if (delegate_->IsDeviceAllowed(*devices[i])) | |
244 notification->devices_added.push_back(devices[i].Pass()); | |
245 } | |
246 callback.Run(notification.Pass()); | |
247 } | 257 } |
248 | 258 |
249 void DeviceManagerImpl::OnDeviceAdded(DeviceInfoPtr device) { | 259 void DeviceManagerImpl::OnDeviceAdded(DeviceInfoPtr device) { |
250 DCHECK(!ContainsKey(devices_removed_, device->guid)); | 260 DCHECK(!ContainsKey(devices_removed_, device->guid)); |
251 devices_added_.push_back(device.Pass()); | 261 devices_added_.push_back(device.Pass()); |
252 MaybeRunDeviceChangesCallback(); | 262 MaybeRunDeviceChangesCallback(); |
253 } | 263 } |
254 | 264 |
255 void DeviceManagerImpl::OnDeviceRemoved(std::string device_guid) { | 265 void DeviceManagerImpl::OnDeviceRemoved(std::string device_guid) { |
256 bool found = false; | 266 bool found = false; |
257 mojo::Array<DeviceInfoPtr> devices_added; | 267 mojo::Array<DeviceInfoPtr> devices_added; |
258 for (size_t i = 0; i < devices_added_.size(); ++i) { | 268 for (size_t i = 0; i < devices_added_.size(); ++i) { |
259 if (devices_added_[i]->guid == device_guid) | 269 if (devices_added_[i]->guid == device_guid) |
260 found = true; | 270 found = true; |
261 else | 271 else |
262 devices_added.push_back(devices_added_[i].Pass()); | 272 devices_added.push_back(devices_added_[i].Pass()); |
263 } | 273 } |
264 devices_added.Swap(&devices_added_); | 274 devices_added.Swap(&devices_added_); |
265 if (!found) | 275 if (!found) { |
Ken Rockot(use gerrit already)
2015/09/02 22:42:33
nit: eh, maybe no {}.
Reilly Grant (use Gerrit)
2015/09/02 23:58:19
Done.
| |
266 devices_removed_.insert(device_guid); | 276 devices_removed_.insert(device_guid); |
277 } | |
267 MaybeRunDeviceChangesCallback(); | 278 MaybeRunDeviceChangesCallback(); |
268 } | 279 } |
269 | 280 |
270 void DeviceManagerImpl::MaybeRunDeviceChangesCallback() { | 281 void DeviceManagerImpl::MaybeRunDeviceChangesCallback() { |
271 if (!device_change_callbacks_.empty()) { | 282 if (!device_change_callbacks_.empty()) { |
283 mojo::Array<DeviceInfoPtr> devices_added; | |
284 devices_added.Swap(&devices_added_); | |
285 std::set<std::string> devices_removed; | |
286 devices_removed.swap(devices_removed_); | |
287 | |
288 mojo::Array<mojo::String> requested_guids(devices_added.size() + | |
289 devices_removed.size()); | |
290 size_t i; | |
Ken Rockot(use gerrit already)
2015/09/02 22:42:33
nit: not a huge fan of a variable like |i| hanging
Reilly Grant (use Gerrit)
2015/09/02 23:58:18
Done.
| |
291 for (i = 0; i < devices_added.size(); ++i) | |
292 requested_guids[i] = devices_added[i]->guid; | |
293 for (const std::string& guid : devices_removed) | |
294 requested_guids[i++] = guid; | |
295 | |
296 permission_request_pending_ = true; | |
Ken Rockot(use gerrit already)
2015/09/02 22:42:33
this doesn't appear to have any logical effect; i'
Reilly Grant (use Gerrit)
2015/09/02 23:58:19
Done.
| |
297 permission_provider_->HasDevicePermission( | |
298 requested_guids.Pass(), | |
299 base::Bind(&DeviceManagerImpl::OnPermissionCheckComplete, | |
300 weak_factory_.GetWeakPtr(), base::Passed(&devices_added), | |
Ken Rockot(use gerrit already)
2015/09/02 22:42:33
nit: No need to use a WeakPtr here. permission_pro
Reilly Grant (use Gerrit)
2015/09/02 23:58:19
Done.
| |
301 devices_removed)); | |
302 } | |
303 } | |
304 | |
305 void DeviceManagerImpl::OnPermissionCheckComplete( | |
306 mojo::Array<DeviceInfoPtr> devices_added, | |
307 const std::set<std::string>& devices_removed, | |
308 mojo::Array<mojo::String> allowed_guids) { | |
309 permission_request_pending_ = false; | |
310 | |
311 if (allowed_guids.size() > 0 || first_notification_) { | |
312 std::set<std::string> allowed_guid_set; | |
313 for (size_t i = 0; i < allowed_guids.size(); ++i) | |
314 allowed_guid_set.insert(allowed_guids[i]); | |
315 | |
272 DeviceChangeNotificationPtr notification = DeviceChangeNotification::New(); | 316 DeviceChangeNotificationPtr notification = DeviceChangeNotification::New(); |
273 notification->devices_added.Swap(&devices_added_); | 317 notification->devices_added.resize(0); |
318 for (size_t i = 0; i < devices_added.size(); ++i) { | |
319 if (ContainsKey(allowed_guid_set, devices_added[i]->guid)) | |
320 notification->devices_added.push_back(devices_added[i].Pass()); | |
321 } | |
322 | |
274 notification->devices_removed.resize(0); | 323 notification->devices_removed.resize(0); |
275 for (const std::string& device : devices_removed_) | 324 for (const std::string& guid : devices_removed) { |
276 notification->devices_removed.push_back(device); | 325 if (ContainsKey(allowed_guid_set, guid)) |
277 devices_removed_.clear(); | 326 notification->devices_removed.push_back(guid); |
Ken Rockot(use gerrit already)
2015/09/02 22:42:33
Should we also omit any guid that would otherwise
Reilly Grant (use Gerrit)
2015/09/02 23:58:19
We know that devices_added and devices_removed are
| |
327 } | |
278 | 328 |
329 DCHECK(!device_change_callbacks_.empty()); | |
279 const GetDeviceChangesCallback& callback = device_change_callbacks_.front(); | 330 const GetDeviceChangesCallback& callback = device_change_callbacks_.front(); |
331 first_notification_ = false; | |
280 callback.Run(notification.Pass()); | 332 callback.Run(notification.Pass()); |
281 device_change_callbacks_.pop(); | 333 device_change_callbacks_.pop(); |
282 } | 334 } |
335 | |
336 if (devices_added_.size() > 0 || !devices_removed_.empty()) { | |
337 MaybeRunDeviceChangesCallback(); | |
338 } | |
283 } | 339 } |
284 | 340 |
285 } // namespace usb | 341 } // namespace usb |
286 } // namespace device | 342 } // namespace device |
OLD | NEW |