Chromium Code Reviews| 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 |