Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(87)

Side by Side Diff: device/devices_app/usb/device_manager_impl.cc

Issue 1342663003: Pass full Mojo USB DeviceInfo object with removal notifications. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/interfaces/device.mojom.h" 17 #include "device/devices_app/usb/public/interfaces/device.mojom.h"
18 #include "device/devices_app/usb/type_converters.h" 18 #include "device/devices_app/usb/type_converters.h"
19 #include "device/usb/usb_device.h" 19 #include "device/usb/usb_device.h"
20 #include "device/usb/usb_device_filter.h" 20 #include "device/usb/usb_device_filter.h"
21 #include "device/usb/usb_service.h" 21 #include "device/usb/usb_service.h"
22 #include "third_party/mojo/src/mojo/public/cpp/bindings/array.h" 22 #include "third_party/mojo/src/mojo/public/cpp/bindings/array.h"
23 #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"
24 24
25 namespace device { 25 namespace device {
26 namespace usb { 26 namespace usb {
27 27
28 namespace { 28 namespace {
29 29
30 typedef std::vector<scoped_refptr<UsbDevice>> DeviceList;
Ken Rockot(use gerrit already) 2015/09/15 18:09:25 nit: Maybe just axe these and use DeviceManagerImp
Reilly Grant (use Gerrit) 2015/09/15 19:46:48 Done.
31 typedef std::map<std::string, scoped_refptr<device::UsbDevice>> DeviceMap;
32
30 void OnGetDevicesOnServiceThread( 33 void OnGetDevicesOnServiceThread(
31 const std::vector<UsbDeviceFilter>& filters, 34 const base::Callback<void(const DeviceList&)>& callback,
32 const base::Callback<void(mojo::Array<DeviceInfoPtr>)>& callback,
33 scoped_refptr<base::TaskRunner> callback_task_runner, 35 scoped_refptr<base::TaskRunner> callback_task_runner,
34 const std::vector<scoped_refptr<UsbDevice>>& devices) { 36 const DeviceList& devices) {
35 mojo::Array<DeviceInfoPtr> mojo_devices(0); 37 callback_task_runner->PostTask(FROM_HERE, base::Bind(callback, devices));
36 for (size_t i = 0; i < devices.size(); ++i) {
37 if (UsbDeviceFilter::MatchesAny(devices[i], filters) || filters.empty())
38 mojo_devices.push_back(DeviceInfo::From(*devices[i]));
39 }
40 callback_task_runner->PostTask(
41 FROM_HERE, base::Bind(callback, base::Passed(&mojo_devices)));
42 } 38 }
43 39
44 void GetDevicesOnServiceThread( 40 void GetDevicesOnServiceThread(
45 const std::vector<UsbDeviceFilter>& filters, 41 const base::Callback<void(const DeviceList&)>& callback,
46 const base::Callback<void(mojo::Array<DeviceInfoPtr>)>& callback,
47 scoped_refptr<base::TaskRunner> callback_task_runner) { 42 scoped_refptr<base::TaskRunner> callback_task_runner) {
48 DCHECK(DeviceClient::Get()); 43 DCHECK(DeviceClient::Get());
49 UsbService* usb_service = DeviceClient::Get()->GetUsbService(); 44 UsbService* usb_service = DeviceClient::Get()->GetUsbService();
50 if (!usb_service) { 45 if (usb_service) {
51 mojo::Array<DeviceInfoPtr> no_devices(0); 46 usb_service->GetDevices(base::Bind(&OnGetDevicesOnServiceThread, callback,
52 callback_task_runner->PostTask( 47 callback_task_runner));
53 FROM_HERE, base::Bind(callback, base::Passed(&no_devices))); 48 } else {
54 return; 49 callback_task_runner->PostTask(FROM_HERE,
50 base::Bind(callback, DeviceList()));
55 } 51 }
56 usb_service->GetDevices(base::Bind(&OnGetDevicesOnServiceThread, filters,
57 callback, callback_task_runner));
58 } 52 }
59 53
60 void RunOpenDeviceCallback(const DeviceManager::OpenDeviceCallback& callback, 54 void RunOpenDeviceCallback(const DeviceManager::OpenDeviceCallback& callback,
61 OpenDeviceError error) { 55 OpenDeviceError error) {
62 callback.Run(error); 56 callback.Run(error);
63 } 57 }
64 58
65 void OnOpenDeviceOnServiceThread( 59 void OnOpenDeviceOnServiceThread(
66 mojo::InterfaceRequest<Device> device_request, 60 mojo::InterfaceRequest<Device> device_request,
67 const DeviceManager::OpenDeviceCallback& callback, 61 const DeviceManager::OpenDeviceCallback& callback,
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 callback_task_runner->PostTask(FROM_HERE, 94 callback_task_runner->PostTask(FROM_HERE,
101 base::Bind(&RunOpenDeviceCallback, callback, 95 base::Bind(&RunOpenDeviceCallback, callback,
102 OPEN_DEVICE_ERROR_NOT_FOUND)); 96 OPEN_DEVICE_ERROR_NOT_FOUND));
103 return; 97 return;
104 } 98 }
105 device->Open(base::Bind(&OnOpenDeviceOnServiceThread, 99 device->Open(base::Bind(&OnOpenDeviceOnServiceThread,
106 base::Passed(&device_request), callback, 100 base::Passed(&device_request), callback,
107 callback_task_runner)); 101 callback_task_runner));
108 } 102 }
109 103
110 void FilterDeviceListAndThen( 104 void FilterAndConvertDevicesAndThen(
105 const DeviceMap& devices,
111 const DeviceManagerImpl::GetDevicesCallback& callback, 106 const DeviceManagerImpl::GetDevicesCallback& callback,
112 mojo::Array<DeviceInfoPtr> devices,
113 mojo::Array<mojo::String> allowed_guids) { 107 mojo::Array<mojo::String> allowed_guids) {
114 std::set<std::string> allowed_guid_set; 108 mojo::Array<DeviceInfoPtr> allowed_devices(allowed_guids.size());
115 for (size_t i = 0; i < allowed_guids.size(); ++i) 109 for (size_t i = 0; i < allowed_guids.size(); ++i) {
116 allowed_guid_set.insert(allowed_guids[i]); 110 const auto it = devices.find(allowed_guids[i]);
117 111 DCHECK(it != devices.end());
118 mojo::Array<DeviceInfoPtr> allowed_devices(0); 112 allowed_devices[i] = DeviceInfo::From(*it->second);
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 } 113 }
123 114
124 callback.Run(allowed_devices.Pass()); 115 callback.Run(allowed_devices.Pass());
125 } 116 }
126 117
127 } // namespace 118 } // namespace
128 119
129 class DeviceManagerImpl::ServiceThreadHelper 120 class DeviceManagerImpl::ServiceThreadHelper
130 : public UsbService::Observer, 121 : public UsbService::Observer,
131 public base::MessageLoop::DestructionObserver { 122 public base::MessageLoop::DestructionObserver {
(...skipping 11 matching lines...) Expand all
143 if (usb_service) 134 if (usb_service)
144 self->observer_.Add(usb_service); 135 self->observer_.Add(usb_service);
145 136
146 // |self| now owned by the current message loop. 137 // |self| now owned by the current message loop.
147 base::MessageLoop::current()->AddDestructionObserver(self.release()); 138 base::MessageLoop::current()->AddDestructionObserver(self.release());
148 } 139 }
149 140
150 private: 141 private:
151 // UsbService::Observer 142 // UsbService::Observer
152 void OnDeviceAdded(scoped_refptr<UsbDevice> device) override { 143 void OnDeviceAdded(scoped_refptr<UsbDevice> device) override {
153 DeviceInfoPtr mojo_device(DeviceInfo::From(*device));
154 task_runner_->PostTask( 144 task_runner_->PostTask(
155 FROM_HERE, base::Bind(&DeviceManagerImpl::OnDeviceAdded, manager_, 145 FROM_HERE,
156 base::Passed(&mojo_device))); 146 base::Bind(&DeviceManagerImpl::OnDeviceAdded, manager_, device));
157 } 147 }
158 148
159 void OnDeviceRemoved(scoped_refptr<UsbDevice> device) override { 149 void OnDeviceRemoved(scoped_refptr<UsbDevice> device) override {
160 task_runner_->PostTask( 150 task_runner_->PostTask(
161 FROM_HERE, base::Bind(&DeviceManagerImpl::OnDeviceRemoved, manager_, 151 FROM_HERE,
162 device->guid())); 152 base::Bind(&DeviceManagerImpl::OnDeviceRemoved, manager_, device));
163 } 153 }
164 154
165 void WillDestroyUsbService() override { observer_.RemoveAll(); } 155 void WillDestroyUsbService() override { observer_.RemoveAll(); }
166 156
167 // base::MessageLoop::DestructionObserver 157 // base::MessageLoop::DestructionObserver
168 void WillDestroyCurrentMessageLoop() override { delete this; } 158 void WillDestroyCurrentMessageLoop() override { delete this; }
169 159
170 ScopedObserver<UsbService, UsbService::Observer> observer_; 160 ScopedObserver<UsbService, UsbService::Observer> observer_;
171 base::WeakPtr<DeviceManagerImpl> manager_; 161 base::WeakPtr<DeviceManagerImpl> manager_;
172 scoped_refptr<base::TaskRunner> task_runner_; 162 scoped_refptr<base::TaskRunner> task_runner_;
(...skipping 23 matching lines...) Expand all
196 186
197 DeviceManagerImpl::~DeviceManagerImpl() { 187 DeviceManagerImpl::~DeviceManagerImpl() {
198 // It is safe to call this if |helper_| was already destroyed when 188 // It is safe to call this if |helper_| was already destroyed when
199 // |service_task_runner_| exited as the task will never execute. 189 // |service_task_runner_| exited as the task will never execute.
200 service_task_runner_->DeleteSoon(FROM_HERE, helper_); 190 service_task_runner_->DeleteSoon(FROM_HERE, helper_);
201 connection_error_handler_.Run(); 191 connection_error_handler_.Run();
202 } 192 }
203 193
204 void DeviceManagerImpl::GetDevices(EnumerationOptionsPtr options, 194 void DeviceManagerImpl::GetDevices(EnumerationOptionsPtr options,
205 const GetDevicesCallback& callback) { 195 const GetDevicesCallback& callback) {
206 std::vector<UsbDeviceFilter> filters; 196 auto get_devices_callback =
207 if (options) 197 base::Bind(&DeviceManagerImpl::OnGetDevices, weak_factory_.GetWeakPtr(),
208 filters = options->filters.To<std::vector<UsbDeviceFilter>>(); 198 base::Passed(&options), callback);
209 auto get_devices_callback = base::Bind(&DeviceManagerImpl::OnGetDevices,
210 weak_factory_.GetWeakPtr(), callback);
211 service_task_runner_->PostTask( 199 service_task_runner_->PostTask(
212 FROM_HERE, 200 FROM_HERE, base::Bind(&GetDevicesOnServiceThread, get_devices_callback,
213 base::Bind(&GetDevicesOnServiceThread, filters, get_devices_callback, 201 base::ThreadTaskRunnerHandle::Get()));
214 base::ThreadTaskRunnerHandle::Get()));
215 } 202 }
216 203
217 void DeviceManagerImpl::GetDeviceChanges( 204 void DeviceManagerImpl::GetDeviceChanges(
218 const GetDeviceChangesCallback& callback) { 205 const GetDeviceChangesCallback& callback) {
219 device_change_callbacks_.push(callback); 206 device_change_callbacks_.push(callback);
220 MaybeRunDeviceChangesCallback(); 207 MaybeRunDeviceChangesCallback();
221 } 208 }
222 209
223 void DeviceManagerImpl::OpenDevice( 210 void DeviceManagerImpl::OpenDevice(
224 const mojo::String& guid, 211 const mojo::String& guid,
(...skipping 17 matching lines...) Expand all
242 return; 229 return;
243 } 230 }
244 231
245 DCHECK(allowed_guids.size() == 1); 232 DCHECK(allowed_guids.size() == 1);
246 service_task_runner_->PostTask( 233 service_task_runner_->PostTask(
247 FROM_HERE, base::Bind(&OpenDeviceOnServiceThread, allowed_guids[0], 234 FROM_HERE, base::Bind(&OpenDeviceOnServiceThread, allowed_guids[0],
248 base::Passed(&device_request), callback, 235 base::Passed(&device_request), callback,
249 base::ThreadTaskRunnerHandle::Get())); 236 base::ThreadTaskRunnerHandle::Get()));
250 } 237 }
251 238
252 void DeviceManagerImpl::OnGetDevices(const GetDevicesCallback& callback, 239 void DeviceManagerImpl::OnGetDevices(EnumerationOptionsPtr options,
253 mojo::Array<DeviceInfoPtr> devices) { 240 const GetDevicesCallback& callback,
254 mojo::Array<mojo::String> requested_guids(devices.size()); 241 const DeviceList& devices) {
255 for (size_t i = 0; i < devices.size(); ++i) 242 std::vector<UsbDeviceFilter> filters;
256 requested_guids[i] = devices[i]->guid; 243 if (options)
244 filters = options->filters.To<std::vector<UsbDeviceFilter>>();
245
246 std::map<std::string, scoped_refptr<UsbDevice>> device_map;
247 mojo::Array<mojo::String> requested_guids(0);
248 for (const auto& device : devices) {
249 if (filters.empty() || UsbDeviceFilter::MatchesAny(device, filters)) {
250 device_map[device->guid()] = device;
251 requested_guids.push_back(device->guid());
252 }
253 }
257 254
258 permission_provider_->HasDevicePermission( 255 permission_provider_->HasDevicePermission(
259 requested_guids.Pass(), 256 requested_guids.Pass(),
260 base::Bind(&FilterDeviceListAndThen, callback, base::Passed(&devices))); 257 base::Bind(&FilterAndConvertDevicesAndThen, device_map, callback));
261 } 258 }
262 259
263 void DeviceManagerImpl::OnDeviceAdded(DeviceInfoPtr device) { 260 void DeviceManagerImpl::OnDeviceAdded(scoped_refptr<UsbDevice> device) {
264 DCHECK(!ContainsKey(devices_removed_, device->guid)); 261 DCHECK(!ContainsKey(devices_removed_, device->guid()));
265 devices_added_.push_back(device.Pass()); 262 devices_added_[device->guid()] = device;
266 MaybeRunDeviceChangesCallback(); 263 MaybeRunDeviceChangesCallback();
267 } 264 }
268 265
269 void DeviceManagerImpl::OnDeviceRemoved(std::string device_guid) { 266 void DeviceManagerImpl::OnDeviceRemoved(scoped_refptr<UsbDevice> device) {
270 bool found = false; 267 if (devices_added_.erase(device->guid()) == 0)
271 mojo::Array<DeviceInfoPtr> devices_added; 268 devices_removed_[device->guid()] = device;
272 for (size_t i = 0; i < devices_added_.size(); ++i) {
273 if (devices_added_[i]->guid == device_guid)
274 found = true;
275 else
276 devices_added.push_back(devices_added_[i].Pass());
277 }
278 devices_added.Swap(&devices_added_);
279 if (!found)
280 devices_removed_.insert(device_guid);
281 MaybeRunDeviceChangesCallback(); 269 MaybeRunDeviceChangesCallback();
282 } 270 }
283 271
284 void DeviceManagerImpl::MaybeRunDeviceChangesCallback() { 272 void DeviceManagerImpl::MaybeRunDeviceChangesCallback() {
285 if (!permission_request_pending_ && !device_change_callbacks_.empty()) { 273 if (!permission_request_pending_ && !device_change_callbacks_.empty()) {
286 mojo::Array<DeviceInfoPtr> devices_added; 274 DeviceMap devices_added;
287 devices_added.Swap(&devices_added_); 275 devices_added.swap(devices_added_);
288 std::set<std::string> devices_removed; 276 DeviceMap devices_removed;
289 devices_removed.swap(devices_removed_); 277 devices_removed.swap(devices_removed_);
290 278
291 mojo::Array<mojo::String> requested_guids(devices_added.size() + 279 mojo::Array<mojo::String> requested_guids(devices_added.size() +
292 devices_removed.size()); 280 devices_removed.size());
293 { 281 {
294 size_t i; 282 size_t i = 0;
295 for (i = 0; i < devices_added.size(); ++i) 283 for (const auto& map_entry : devices_added)
296 requested_guids[i] = devices_added[i]->guid; 284 requested_guids[i++] = map_entry.first;
297 for (const std::string& guid : devices_removed) 285 for (const auto& map_entry : devices_removed)
298 requested_guids[i++] = guid; 286 requested_guids[i++] = map_entry.first;
299 } 287 }
300 288
301 permission_request_pending_ = true; 289 permission_request_pending_ = true;
302 permission_provider_->HasDevicePermission( 290 permission_provider_->HasDevicePermission(
303 requested_guids.Pass(), 291 requested_guids.Pass(),
304 base::Bind(&DeviceManagerImpl::OnEnumerationPermissionCheckComplete, 292 base::Bind(&DeviceManagerImpl::OnEnumerationPermissionCheckComplete,
305 base::Unretained(this), base::Passed(&devices_added), 293 base::Unretained(this), devices_added, devices_removed));
306 devices_removed));
307 } 294 }
308 } 295 }
309 296
310 void DeviceManagerImpl::OnEnumerationPermissionCheckComplete( 297 void DeviceManagerImpl::OnEnumerationPermissionCheckComplete(
311 mojo::Array<DeviceInfoPtr> devices_added, 298 const DeviceMap& devices_added,
312 const std::set<std::string>& devices_removed, 299 const DeviceMap& devices_removed,
313 mojo::Array<mojo::String> allowed_guids) { 300 mojo::Array<mojo::String> allowed_guids) {
314 permission_request_pending_ = false; 301 permission_request_pending_ = false;
315 302
316 if (allowed_guids.size() > 0) { 303 if (allowed_guids.size() > 0) {
317 std::set<std::string> allowed_guid_set;
318 for (size_t i = 0; i < allowed_guids.size(); ++i)
319 allowed_guid_set.insert(allowed_guids[i]);
320
321 DeviceChangeNotificationPtr notification = DeviceChangeNotification::New(); 304 DeviceChangeNotificationPtr notification = DeviceChangeNotification::New();
322 notification->devices_added.resize(0); 305 notification->devices_added.resize(0);
323 for (size_t i = 0; i < devices_added.size(); ++i) { 306 notification->devices_removed.resize(0);
324 if (ContainsKey(allowed_guid_set, devices_added[i]->guid))
325 notification->devices_added.push_back(devices_added[i].Pass());
326 }
327 307
328 notification->devices_removed.resize(0); 308 for (size_t i = 0; i < allowed_guids.size(); ++i) {
329 for (const std::string& guid : devices_removed) { 309 const mojo::String& guid = allowed_guids[i];
330 if (ContainsKey(allowed_guid_set, guid)) 310 auto it = devices_added.find(guid);
331 notification->devices_removed.push_back(guid); 311 if (it != devices_added.end()) {
312 DCHECK(!ContainsKey(devices_removed, guid));
313 notification->devices_added.push_back(DeviceInfo::From(*it->second));
314 } else {
315 it = devices_removed.find(guid);
316 DCHECK(it != devices_removed.end());
317 notification->devices_removed.push_back(DeviceInfo::From(*it->second));
318 }
332 } 319 }
333 320
334 DCHECK(!device_change_callbacks_.empty()); 321 DCHECK(!device_change_callbacks_.empty());
335 const GetDeviceChangesCallback& callback = device_change_callbacks_.front(); 322 const GetDeviceChangesCallback& callback = device_change_callbacks_.front();
336 callback.Run(notification.Pass()); 323 callback.Run(notification.Pass());
337 device_change_callbacks_.pop(); 324 device_change_callbacks_.pop();
338 } 325 }
339 326
340 if (devices_added_.size() > 0 || !devices_removed_.empty()) 327 if (devices_added_.size() > 0 || !devices_removed_.empty())
341 MaybeRunDeviceChangesCallback(); 328 MaybeRunDeviceChangesCallback();
342 } 329 }
343 330
344 } // namespace usb 331 } // namespace usb
345 } // namespace device 332 } // namespace device
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698