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 |
| 121 ~ServiceThreadHelper() override { | 137 ~ServiceThreadHelper() override { |
| 122 base::MessageLoop::current()->RemoveDestructionObserver(this); | 138 base::MessageLoop::current()->RemoveDestructionObserver(this); |
| 123 } | 139 } |
| 124 | 140 |
| 125 static void Start( | 141 static void Start(scoped_ptr<ServiceThreadHelper> self) { |
| 126 scoped_ptr<ServiceThreadHelper> self, | |
| 127 const base::Callback<void(mojo::Array<DeviceInfoPtr>)>& callback) { | |
| 128 UsbService* usb_service = DeviceClient::Get()->GetUsbService(); | 142 UsbService* usb_service = DeviceClient::Get()->GetUsbService(); |
| 129 if (usb_service) { | 143 if (usb_service) |
| 130 self->observer_.Add(usb_service); | 144 self->observer_.Add(usb_service); |
| 131 std::vector<UsbDeviceFilter> no_filters; | |
| 132 usb_service->GetDevices(base::Bind(&OnGetDevicesOnServiceThread, | |
| 133 no_filters, callback, | |
| 134 self->task_runner_)); | |
| 135 } | |
| 136 | 145 |
| 137 // |self| now owned by the current message loop. | 146 // |self| now owned by the current message loop. |
| 138 base::MessageLoop::current()->AddDestructionObserver(self.release()); | 147 base::MessageLoop::current()->AddDestructionObserver(self.release()); |
| 139 } | 148 } |
| 140 | 149 |
| 141 private: | 150 private: |
| 142 // UsbService::Observer | 151 // UsbService::Observer |
| 143 void OnDeviceAdded(scoped_refptr<UsbDevice> device) override { | 152 void OnDeviceAdded(scoped_refptr<UsbDevice> device) override { |
| 144 DeviceInfoPtr mojo_device(DeviceInfo::From(*device)); | 153 DeviceInfoPtr mojo_device(DeviceInfo::From(*device)); |
| 145 task_runner_->PostTask( | 154 task_runner_->PostTask( |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 156 // base::MessageLoop::DestructionObserver | 165 // base::MessageLoop::DestructionObserver |
| 157 void WillDestroyCurrentMessageLoop() override { delete this; } | 166 void WillDestroyCurrentMessageLoop() override { delete this; } |
| 158 | 167 |
| 159 ScopedObserver<UsbService, UsbService::Observer> observer_; | 168 ScopedObserver<UsbService, UsbService::Observer> observer_; |
| 160 base::WeakPtr<DeviceManagerImpl> manager_; | 169 base::WeakPtr<DeviceManagerImpl> manager_; |
| 161 scoped_refptr<base::TaskRunner> task_runner_; | 170 scoped_refptr<base::TaskRunner> task_runner_; |
| 162 }; | 171 }; |
| 163 | 172 |
| 164 DeviceManagerImpl::DeviceManagerImpl( | 173 DeviceManagerImpl::DeviceManagerImpl( |
| 165 mojo::InterfaceRequest<DeviceManager> request, | 174 mojo::InterfaceRequest<DeviceManager> request, |
| 166 scoped_ptr<DeviceManagerDelegate> delegate, | 175 PermissionProviderPtr permission_provider, |
| 167 scoped_refptr<base::SequencedTaskRunner> service_task_runner) | 176 scoped_refptr<base::SequencedTaskRunner> service_task_runner) |
| 168 : binding_(this, request.Pass()), | 177 : permission_provider_(permission_provider.Pass()), |
| 169 delegate_(delegate.Pass()), | |
| 170 service_task_runner_(service_task_runner), | 178 service_task_runner_(service_task_runner), |
| 179 binding_(this, request.Pass()), | |
| 171 weak_factory_(this) { | 180 weak_factory_(this) { |
| 181 // This object owns itself and will be destroyed if either the message pipe | |
| 182 // it is bound to is closed or the PermissionProvider it depends on is | |
| 183 // unavailable. | |
| 184 binding_.set_connection_error_handler([this]() { delete this; }); | |
| 185 permission_provider_.set_connection_error_handler([this]() { delete this; }); | |
| 186 | |
| 187 scoped_ptr<ServiceThreadHelper> helper(new ServiceThreadHelper( | |
| 188 weak_factory_.GetWeakPtr(), base::ThreadTaskRunnerHandle::Get())); | |
| 189 helper_ = helper.get(); | |
| 190 service_task_runner_->PostTask( | |
| 191 FROM_HERE, | |
| 192 base::Bind(&ServiceThreadHelper::Start, base::Passed(&helper))); | |
| 172 } | 193 } |
| 173 | 194 |
| 174 DeviceManagerImpl::~DeviceManagerImpl() { | 195 DeviceManagerImpl::~DeviceManagerImpl() { |
| 175 if (helper_) { | 196 // It is safe to call this if |helper_| was already destroyed when |
| 176 // It is safe to call this if |helper_| was already destroyed when | 197 // |service_task_runner_| exited as the task will never execute. |
| 177 // |service_task_runner_| exited as the task will never execute. | 198 service_task_runner_->DeleteSoon(FROM_HERE, helper_); |
| 178 service_task_runner_->DeleteSoon(FROM_HERE, helper_); | 199 connection_error_handler_.Run(); |
| 179 } | |
| 180 } | |
| 181 | |
| 182 void DeviceManagerImpl::set_connection_error_handler( | |
| 183 const mojo::Closure& error_handler) { | |
| 184 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 std::vector<UsbDeviceFilter> filters; |
| 205 if (options) | |
| 206 filters = options->filters.To<std::vector<UsbDeviceFilter>>(); | |
| 190 auto get_devices_callback = base::Bind(&DeviceManagerImpl::OnGetDevices, | 207 auto get_devices_callback = base::Bind(&DeviceManagerImpl::OnGetDevices, |
| 191 weak_factory_.GetWeakPtr(), callback); | 208 weak_factory_.GetWeakPtr(), callback); |
| 192 service_task_runner_->PostTask( | 209 service_task_runner_->PostTask( |
| 193 FROM_HERE, | 210 FROM_HERE, |
| 194 base::Bind(&GetDevicesOnServiceThread, filters, get_devices_callback, | 211 base::Bind(&GetDevicesOnServiceThread, filters, get_devices_callback, |
| 195 base::ThreadTaskRunnerHandle::Get())); | 212 base::ThreadTaskRunnerHandle::Get())); |
| 196 } | 213 } |
| 197 | 214 |
| 198 void DeviceManagerImpl::GetDeviceChanges( | 215 void DeviceManagerImpl::GetDeviceChanges( |
| 199 const GetDeviceChangesCallback& callback) { | 216 const GetDeviceChangesCallback& callback) { |
| 200 if (helper_) { | 217 device_change_callbacks_.push(callback); |
| 201 device_change_callbacks_.push(callback); | 218 MaybeRunDeviceChangesCallback(); |
| 202 MaybeRunDeviceChangesCallback(); | |
| 203 } else { | |
| 204 scoped_ptr<ServiceThreadHelper> helper(new ServiceThreadHelper( | |
| 205 weak_factory_.GetWeakPtr(), base::ThreadTaskRunnerHandle::Get())); | |
| 206 helper_ = helper.get(); | |
| 207 auto get_devices_callback = | |
| 208 base::Bind(&DeviceManagerImpl::OnGetInitialDevices, | |
| 209 weak_factory_.GetWeakPtr(), callback); | |
| 210 service_task_runner_->PostTask( | |
| 211 FROM_HERE, base::Bind(&ServiceThreadHelper::Start, | |
| 212 base::Passed(&helper), get_devices_callback)); | |
| 213 } | |
| 214 } | 219 } |
| 215 | 220 |
| 216 void DeviceManagerImpl::OpenDevice( | 221 void DeviceManagerImpl::OpenDevice( |
| 217 const mojo::String& guid, | 222 const mojo::String& guid, |
| 218 mojo::InterfaceRequest<Device> device_request, | 223 mojo::InterfaceRequest<Device> device_request, |
| 219 const OpenDeviceCallback& callback) { | 224 const OpenDeviceCallback& callback) { |
| 220 service_task_runner_->PostTask( | 225 service_task_runner_->PostTask( |
| 221 FROM_HERE, base::Bind(&OpenDeviceOnServiceThread, guid, | 226 FROM_HERE, base::Bind(&OpenDeviceOnServiceThread, guid, |
| 222 base::Passed(&device_request), callback, | 227 base::Passed(&device_request), callback, |
| 223 base::ThreadTaskRunnerHandle::Get())); | 228 base::ThreadTaskRunnerHandle::Get())); |
| 224 } | 229 } |
| 225 | 230 |
| 226 void DeviceManagerImpl::OnGetDevices(const GetDevicesCallback& callback, | 231 void DeviceManagerImpl::OnGetDevices(const GetDevicesCallback& callback, |
| 227 mojo::Array<DeviceInfoPtr> devices) { | 232 mojo::Array<DeviceInfoPtr> devices) { |
| 228 mojo::Array<DeviceInfoPtr> allowed_devices(0); | 233 mojo::Array<mojo::String> requested_guids(devices.size()); |
| 229 for (size_t i = 0; i < devices.size(); ++i) { | 234 for (size_t i = 0; i < devices.size(); ++i) { |
|
Ken Rockot(use gerrit already)
2015/09/03 00:06:11
extra nitty nit: no {}
Reilly Grant (use Gerrit)
2015/09/03 00:09:28
Done.
| |
| 230 if (delegate_->IsDeviceAllowed(*devices[i])) | 235 requested_guids[i] = devices[i]->guid; |
| 231 allowed_devices.push_back(devices[i].Pass()); | |
| 232 } | 236 } |
| 233 callback.Run(allowed_devices.Pass()); | 237 permission_provider_->HasDevicePermission( |
| 234 } | 238 requested_guids.Pass(), |
| 235 | 239 base::Bind(&FilterDeviceListAndThen, callback, base::Passed(&devices))); |
| 236 void DeviceManagerImpl::OnGetInitialDevices( | |
| 237 const GetDeviceChangesCallback& callback, | |
| 238 mojo::Array<DeviceInfoPtr> devices) { | |
| 239 DeviceChangeNotificationPtr notification = DeviceChangeNotification::New(); | |
| 240 notification->devices_added = mojo::Array<DeviceInfoPtr>::New(0); | |
| 241 notification->devices_removed = mojo::Array<mojo::String>::New(0); | |
| 242 for (size_t i = 0; i < devices.size(); ++i) { | |
| 243 if (delegate_->IsDeviceAllowed(*devices[i])) | |
| 244 notification->devices_added.push_back(devices[i].Pass()); | |
| 245 } | |
| 246 callback.Run(notification.Pass()); | |
| 247 } | 240 } |
| 248 | 241 |
| 249 void DeviceManagerImpl::OnDeviceAdded(DeviceInfoPtr device) { | 242 void DeviceManagerImpl::OnDeviceAdded(DeviceInfoPtr device) { |
| 250 DCHECK(!ContainsKey(devices_removed_, device->guid)); | 243 DCHECK(!ContainsKey(devices_removed_, device->guid)); |
| 251 devices_added_.push_back(device.Pass()); | 244 devices_added_.push_back(device.Pass()); |
| 252 MaybeRunDeviceChangesCallback(); | 245 MaybeRunDeviceChangesCallback(); |
| 253 } | 246 } |
| 254 | 247 |
| 255 void DeviceManagerImpl::OnDeviceRemoved(std::string device_guid) { | 248 void DeviceManagerImpl::OnDeviceRemoved(std::string device_guid) { |
| 256 bool found = false; | 249 bool found = false; |
| 257 mojo::Array<DeviceInfoPtr> devices_added; | 250 mojo::Array<DeviceInfoPtr> devices_added; |
| 258 for (size_t i = 0; i < devices_added_.size(); ++i) { | 251 for (size_t i = 0; i < devices_added_.size(); ++i) { |
| 259 if (devices_added_[i]->guid == device_guid) | 252 if (devices_added_[i]->guid == device_guid) |
| 260 found = true; | 253 found = true; |
| 261 else | 254 else |
| 262 devices_added.push_back(devices_added_[i].Pass()); | 255 devices_added.push_back(devices_added_[i].Pass()); |
| 263 } | 256 } |
| 264 devices_added.Swap(&devices_added_); | 257 devices_added.Swap(&devices_added_); |
| 265 if (!found) | 258 if (!found) |
| 266 devices_removed_.insert(device_guid); | 259 devices_removed_.insert(device_guid); |
| 267 MaybeRunDeviceChangesCallback(); | 260 MaybeRunDeviceChangesCallback(); |
| 268 } | 261 } |
| 269 | 262 |
| 270 void DeviceManagerImpl::MaybeRunDeviceChangesCallback() { | 263 void DeviceManagerImpl::MaybeRunDeviceChangesCallback() { |
| 271 if (!device_change_callbacks_.empty()) { | 264 if (!permission_request_pending_ && !device_change_callbacks_.empty()) { |
| 265 mojo::Array<DeviceInfoPtr> devices_added; | |
| 266 devices_added.Swap(&devices_added_); | |
| 267 std::set<std::string> devices_removed; | |
| 268 devices_removed.swap(devices_removed_); | |
| 269 | |
| 270 mojo::Array<mojo::String> requested_guids(devices_added.size() + | |
| 271 devices_removed.size()); | |
| 272 { | |
| 273 size_t i; | |
| 274 for (i = 0; i < devices_added.size(); ++i) | |
| 275 requested_guids[i] = devices_added[i]->guid; | |
| 276 for (const std::string& guid : devices_removed) | |
| 277 requested_guids[i++] = guid; | |
| 278 } | |
| 279 | |
| 280 permission_request_pending_ = true; | |
| 281 permission_provider_->HasDevicePermission( | |
| 282 requested_guids.Pass(), | |
| 283 base::Bind(&DeviceManagerImpl::OnPermissionCheckComplete, | |
| 284 base::Unretained(this), base::Passed(&devices_added), | |
| 285 devices_removed)); | |
| 286 } | |
| 287 } | |
| 288 | |
| 289 void DeviceManagerImpl::OnPermissionCheckComplete( | |
| 290 mojo::Array<DeviceInfoPtr> devices_added, | |
| 291 const std::set<std::string>& devices_removed, | |
| 292 mojo::Array<mojo::String> allowed_guids) { | |
| 293 permission_request_pending_ = false; | |
| 294 | |
| 295 if (allowed_guids.size() > 0) { | |
| 296 std::set<std::string> allowed_guid_set; | |
| 297 for (size_t i = 0; i < allowed_guids.size(); ++i) | |
| 298 allowed_guid_set.insert(allowed_guids[i]); | |
| 299 | |
| 272 DeviceChangeNotificationPtr notification = DeviceChangeNotification::New(); | 300 DeviceChangeNotificationPtr notification = DeviceChangeNotification::New(); |
| 273 notification->devices_added.Swap(&devices_added_); | 301 notification->devices_added.resize(0); |
| 302 for (size_t i = 0; i < devices_added.size(); ++i) { | |
| 303 if (ContainsKey(allowed_guid_set, devices_added[i]->guid)) | |
| 304 notification->devices_added.push_back(devices_added[i].Pass()); | |
| 305 } | |
| 306 | |
| 274 notification->devices_removed.resize(0); | 307 notification->devices_removed.resize(0); |
| 275 for (const std::string& device : devices_removed_) | 308 for (const std::string& guid : devices_removed) { |
| 276 notification->devices_removed.push_back(device); | 309 if (ContainsKey(allowed_guid_set, guid)) |
| 277 devices_removed_.clear(); | 310 notification->devices_removed.push_back(guid); |
| 311 } | |
| 278 | 312 |
| 313 DCHECK(!device_change_callbacks_.empty()); | |
| 279 const GetDeviceChangesCallback& callback = device_change_callbacks_.front(); | 314 const GetDeviceChangesCallback& callback = device_change_callbacks_.front(); |
| 280 callback.Run(notification.Pass()); | 315 callback.Run(notification.Pass()); |
| 281 device_change_callbacks_.pop(); | 316 device_change_callbacks_.pop(); |
| 282 } | 317 } |
| 318 | |
| 319 if (devices_added_.size() > 0 || !devices_removed_.empty()) { | |
| 320 MaybeRunDeviceChangesCallback(); | |
| 321 } | |
| 283 } | 322 } |
| 284 | 323 |
| 285 } // namespace usb | 324 } // namespace usb |
| 286 } // namespace device | 325 } // namespace device |
| OLD | NEW |