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) { |
| 225 mojo::Array<mojo::String> requested_guids(1); |
| 226 requested_guids[0] = guid; |
| 227 permission_provider_->HasDevicePermission( |
| 228 requested_guids.Pass(), |
| 229 base::Bind(&DeviceManagerImpl::OnOpenDevicePermissionCheckComplete, |
| 230 base::Unretained(this), base::Passed(&device_request), |
| 231 callback)); |
| 232 } |
| 233 |
| 234 void DeviceManagerImpl::OnOpenDevicePermissionCheckComplete( |
| 235 mojo::InterfaceRequest<Device> device_request, |
| 236 const OpenDeviceCallback& callback, |
| 237 mojo::Array<mojo::String> allowed_guids) { |
| 238 if (allowed_guids.size() == 0) { |
| 239 callback.Run(OPEN_DEVICE_ERROR_ACCESS_DENIED); |
| 240 return; |
| 241 } |
| 242 |
| 243 DCHECK(allowed_guids.size() == 1); |
220 service_task_runner_->PostTask( | 244 service_task_runner_->PostTask( |
221 FROM_HERE, base::Bind(&OpenDeviceOnServiceThread, guid, | 245 FROM_HERE, base::Bind(&OpenDeviceOnServiceThread, allowed_guids[0], |
222 base::Passed(&device_request), callback, | 246 base::Passed(&device_request), callback, |
223 base::ThreadTaskRunnerHandle::Get())); | 247 base::ThreadTaskRunnerHandle::Get())); |
224 } | 248 } |
225 | 249 |
226 void DeviceManagerImpl::OnGetDevices(const GetDevicesCallback& callback, | 250 void DeviceManagerImpl::OnGetDevices(const GetDevicesCallback& callback, |
227 mojo::Array<DeviceInfoPtr> devices) { | 251 mojo::Array<DeviceInfoPtr> devices) { |
228 mojo::Array<DeviceInfoPtr> allowed_devices(0); | 252 mojo::Array<mojo::String> requested_guids(devices.size()); |
229 for (size_t i = 0; i < devices.size(); ++i) { | 253 for (size_t i = 0; i < devices.size(); ++i) |
230 if (delegate_->IsDeviceAllowed(*devices[i])) | 254 requested_guids[i] = devices[i]->guid; |
231 allowed_devices.push_back(devices[i].Pass()); | |
232 } | |
233 callback.Run(allowed_devices.Pass()); | |
234 } | |
235 | 255 |
236 void DeviceManagerImpl::OnGetInitialDevices( | 256 permission_provider_->HasDevicePermission( |
237 const GetDeviceChangesCallback& callback, | 257 requested_guids.Pass(), |
238 mojo::Array<DeviceInfoPtr> devices) { | 258 base::Bind(&FilterDeviceListAndThen, callback, base::Passed(&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 } | 259 } |
248 | 260 |
249 void DeviceManagerImpl::OnDeviceAdded(DeviceInfoPtr device) { | 261 void DeviceManagerImpl::OnDeviceAdded(DeviceInfoPtr device) { |
250 DCHECK(!ContainsKey(devices_removed_, device->guid)); | 262 DCHECK(!ContainsKey(devices_removed_, device->guid)); |
251 devices_added_.push_back(device.Pass()); | 263 devices_added_.push_back(device.Pass()); |
252 MaybeRunDeviceChangesCallback(); | 264 MaybeRunDeviceChangesCallback(); |
253 } | 265 } |
254 | 266 |
255 void DeviceManagerImpl::OnDeviceRemoved(std::string device_guid) { | 267 void DeviceManagerImpl::OnDeviceRemoved(std::string device_guid) { |
256 bool found = false; | 268 bool found = false; |
257 mojo::Array<DeviceInfoPtr> devices_added; | 269 mojo::Array<DeviceInfoPtr> devices_added; |
258 for (size_t i = 0; i < devices_added_.size(); ++i) { | 270 for (size_t i = 0; i < devices_added_.size(); ++i) { |
259 if (devices_added_[i]->guid == device_guid) | 271 if (devices_added_[i]->guid == device_guid) |
260 found = true; | 272 found = true; |
261 else | 273 else |
262 devices_added.push_back(devices_added_[i].Pass()); | 274 devices_added.push_back(devices_added_[i].Pass()); |
263 } | 275 } |
264 devices_added.Swap(&devices_added_); | 276 devices_added.Swap(&devices_added_); |
265 if (!found) | 277 if (!found) |
266 devices_removed_.insert(device_guid); | 278 devices_removed_.insert(device_guid); |
267 MaybeRunDeviceChangesCallback(); | 279 MaybeRunDeviceChangesCallback(); |
268 } | 280 } |
269 | 281 |
270 void DeviceManagerImpl::MaybeRunDeviceChangesCallback() { | 282 void DeviceManagerImpl::MaybeRunDeviceChangesCallback() { |
271 if (!device_change_callbacks_.empty()) { | 283 if (!permission_request_pending_ && !device_change_callbacks_.empty()) { |
| 284 mojo::Array<DeviceInfoPtr> devices_added; |
| 285 devices_added.Swap(&devices_added_); |
| 286 std::set<std::string> devices_removed; |
| 287 devices_removed.swap(devices_removed_); |
| 288 |
| 289 mojo::Array<mojo::String> requested_guids(devices_added.size() + |
| 290 devices_removed.size()); |
| 291 { |
| 292 size_t i; |
| 293 for (i = 0; i < devices_added.size(); ++i) |
| 294 requested_guids[i] = devices_added[i]->guid; |
| 295 for (const std::string& guid : devices_removed) |
| 296 requested_guids[i++] = guid; |
| 297 } |
| 298 |
| 299 permission_request_pending_ = true; |
| 300 permission_provider_->HasDevicePermission( |
| 301 requested_guids.Pass(), |
| 302 base::Bind(&DeviceManagerImpl::OnEnumerationPermissionCheckComplete, |
| 303 base::Unretained(this), base::Passed(&devices_added), |
| 304 devices_removed)); |
| 305 } |
| 306 } |
| 307 |
| 308 void DeviceManagerImpl::OnEnumerationPermissionCheckComplete( |
| 309 mojo::Array<DeviceInfoPtr> devices_added, |
| 310 const std::set<std::string>& devices_removed, |
| 311 mojo::Array<mojo::String> allowed_guids) { |
| 312 permission_request_pending_ = false; |
| 313 |
| 314 if (allowed_guids.size() > 0) { |
| 315 std::set<std::string> allowed_guid_set; |
| 316 for (size_t i = 0; i < allowed_guids.size(); ++i) |
| 317 allowed_guid_set.insert(allowed_guids[i]); |
| 318 |
272 DeviceChangeNotificationPtr notification = DeviceChangeNotification::New(); | 319 DeviceChangeNotificationPtr notification = DeviceChangeNotification::New(); |
273 notification->devices_added.Swap(&devices_added_); | 320 notification->devices_added.resize(0); |
| 321 for (size_t i = 0; i < devices_added.size(); ++i) { |
| 322 if (ContainsKey(allowed_guid_set, devices_added[i]->guid)) |
| 323 notification->devices_added.push_back(devices_added[i].Pass()); |
| 324 } |
| 325 |
274 notification->devices_removed.resize(0); | 326 notification->devices_removed.resize(0); |
275 for (const std::string& device : devices_removed_) | 327 for (const std::string& guid : devices_removed) { |
276 notification->devices_removed.push_back(device); | 328 if (ContainsKey(allowed_guid_set, guid)) |
277 devices_removed_.clear(); | 329 notification->devices_removed.push_back(guid); |
| 330 } |
278 | 331 |
| 332 DCHECK(!device_change_callbacks_.empty()); |
279 const GetDeviceChangesCallback& callback = device_change_callbacks_.front(); | 333 const GetDeviceChangesCallback& callback = device_change_callbacks_.front(); |
280 callback.Run(notification.Pass()); | 334 callback.Run(notification.Pass()); |
281 device_change_callbacks_.pop(); | 335 device_change_callbacks_.pop(); |
282 } | 336 } |
| 337 |
| 338 if (devices_added_.size() > 0 || !devices_removed_.empty()) |
| 339 MaybeRunDeviceChangesCallback(); |
283 } | 340 } |
284 | 341 |
285 } // namespace usb | 342 } // namespace usb |
286 } // namespace device | 343 } // namespace device |
OLD | NEW |