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" | |
11 #include "base/scoped_observer.h" | |
12 #include "base/sequenced_task_runner.h" | |
13 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
14 #include "base/thread_task_runner_handle.h" | |
15 #include "device/core/device_client.h" | 11 #include "device/core/device_client.h" |
16 #include "device/devices_app/usb/device_impl.h" | 12 #include "device/devices_app/usb/device_impl.h" |
17 #include "device/devices_app/usb/public/interfaces/device.mojom.h" | 13 #include "device/devices_app/usb/public/interfaces/device.mojom.h" |
18 #include "device/devices_app/usb/type_converters.h" | 14 #include "device/devices_app/usb/type_converters.h" |
19 #include "device/usb/usb_device.h" | 15 #include "device/usb/usb_device.h" |
20 #include "device/usb/usb_device_filter.h" | 16 #include "device/usb/usb_device_filter.h" |
21 #include "device/usb/usb_service.h" | 17 #include "device/usb/usb_service.h" |
22 #include "third_party/mojo/src/mojo/public/cpp/bindings/array.h" | 18 #include "third_party/mojo/src/mojo/public/cpp/bindings/array.h" |
23 #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" | 19 #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" |
24 | 20 |
25 namespace device { | 21 namespace device { |
26 namespace usb { | 22 namespace usb { |
27 | 23 |
28 namespace { | 24 namespace { |
29 | 25 |
30 using DeviceList = DeviceManagerImpl::DeviceList; | 26 using DeviceList = DeviceManagerImpl::DeviceList; |
31 using DeviceMap = DeviceManagerImpl::DeviceMap; | 27 using DeviceMap = DeviceManagerImpl::DeviceMap; |
32 | 28 |
33 void OnGetDevicesOnServiceThread( | |
34 const base::Callback<void(const DeviceList&)>& callback, | |
35 scoped_refptr<base::TaskRunner> callback_task_runner, | |
36 const DeviceList& devices) { | |
37 callback_task_runner->PostTask(FROM_HERE, base::Bind(callback, devices)); | |
38 } | |
39 | |
40 void GetDevicesOnServiceThread( | |
41 const base::Callback<void(const DeviceList&)>& callback, | |
42 scoped_refptr<base::TaskRunner> callback_task_runner) { | |
43 DCHECK(DeviceClient::Get()); | |
44 UsbService* usb_service = DeviceClient::Get()->GetUsbService(); | |
45 if (usb_service) { | |
46 usb_service->GetDevices(base::Bind(&OnGetDevicesOnServiceThread, callback, | |
47 callback_task_runner)); | |
48 } else { | |
49 callback_task_runner->PostTask(FROM_HERE, | |
50 base::Bind(callback, DeviceList())); | |
51 } | |
52 } | |
53 | |
54 void GetDeviceOnServiceThread( | |
55 const mojo::String& guid, | |
56 const base::Callback<void(scoped_refptr<UsbDevice>)>& callback, | |
57 scoped_refptr<base::TaskRunner> callback_task_runner) { | |
58 DCHECK(DeviceClient::Get()); | |
59 scoped_refptr<UsbDevice> device; | |
60 UsbService* usb_service = DeviceClient::Get()->GetUsbService(); | |
61 if (usb_service) | |
62 device = usb_service->GetDevice(guid); | |
63 callback_task_runner->PostTask(FROM_HERE, base::Bind(callback, device)); | |
64 } | |
65 | |
66 void FilterAndConvertDevicesAndThen( | 29 void FilterAndConvertDevicesAndThen( |
67 const DeviceMap& devices, | 30 const DeviceMap& devices, |
68 const DeviceManagerImpl::GetDevicesCallback& callback, | 31 const DeviceManagerImpl::GetDevicesCallback& callback, |
69 mojo::Array<mojo::String> allowed_guids) { | 32 mojo::Array<mojo::String> allowed_guids) { |
70 mojo::Array<DeviceInfoPtr> allowed_devices(allowed_guids.size()); | 33 mojo::Array<DeviceInfoPtr> allowed_devices(allowed_guids.size()); |
71 for (size_t i = 0; i < allowed_guids.size(); ++i) { | 34 for (size_t i = 0; i < allowed_guids.size(); ++i) { |
72 const auto it = devices.find(allowed_guids[i]); | 35 const auto it = devices.find(allowed_guids[i]); |
73 DCHECK(it != devices.end()); | 36 DCHECK(it != devices.end()); |
74 allowed_devices[i] = DeviceInfo::From(*it->second); | 37 allowed_devices[i] = DeviceInfo::From(*it->second); |
75 } | 38 } |
76 | 39 |
77 callback.Run(allowed_devices.Pass()); | 40 callback.Run(allowed_devices.Pass()); |
78 } | 41 } |
79 | 42 |
80 } // namespace | 43 } // namespace |
81 | 44 |
82 class DeviceManagerImpl::ServiceThreadHelper | 45 // static |
83 : public UsbService::Observer, | 46 void DeviceManagerImpl::Create(PermissionProviderPtr permission_provider, |
84 public base::MessageLoop::DestructionObserver { | 47 mojo::InterfaceRequest<DeviceManager> request) { |
85 public: | 48 // The created object is owned by its binding. |
86 ServiceThreadHelper(base::WeakPtr<DeviceManagerImpl> manager, | 49 new DeviceManagerImpl(permission_provider.Pass(), request.Pass()); |
87 scoped_refptr<base::TaskRunner> task_runner) | 50 } |
88 : observer_(this), manager_(manager), task_runner_(task_runner) {} | |
89 | |
90 ~ServiceThreadHelper() override { | |
91 base::MessageLoop::current()->RemoveDestructionObserver(this); | |
92 } | |
93 | |
94 static void Start(scoped_ptr<ServiceThreadHelper> self) { | |
95 UsbService* usb_service = DeviceClient::Get()->GetUsbService(); | |
96 if (usb_service) | |
97 self->observer_.Add(usb_service); | |
98 | |
99 // |self| now owned by the current message loop. | |
100 base::MessageLoop::current()->AddDestructionObserver(self.release()); | |
101 } | |
102 | |
103 private: | |
104 // UsbService::Observer | |
105 void OnDeviceAdded(scoped_refptr<UsbDevice> device) override { | |
106 task_runner_->PostTask( | |
107 FROM_HERE, | |
108 base::Bind(&DeviceManagerImpl::OnDeviceAdded, manager_, device)); | |
109 } | |
110 | |
111 void OnDeviceRemoved(scoped_refptr<UsbDevice> device) override { | |
112 task_runner_->PostTask( | |
113 FROM_HERE, | |
114 base::Bind(&DeviceManagerImpl::OnDeviceRemoved, manager_, device)); | |
115 } | |
116 | |
117 void WillDestroyUsbService() override { observer_.RemoveAll(); } | |
118 | |
119 // base::MessageLoop::DestructionObserver | |
120 void WillDestroyCurrentMessageLoop() override { delete this; } | |
121 | |
122 ScopedObserver<UsbService, UsbService::Observer> observer_; | |
123 base::WeakPtr<DeviceManagerImpl> manager_; | |
124 scoped_refptr<base::TaskRunner> task_runner_; | |
125 }; | |
126 | 51 |
127 DeviceManagerImpl::DeviceManagerImpl( | 52 DeviceManagerImpl::DeviceManagerImpl( |
128 mojo::InterfaceRequest<DeviceManager> request, | |
129 PermissionProviderPtr permission_provider, | 53 PermissionProviderPtr permission_provider, |
130 scoped_refptr<base::SequencedTaskRunner> service_task_runner) | 54 mojo::InterfaceRequest<DeviceManager> request) |
131 : permission_provider_(permission_provider.Pass()), | 55 : permission_provider_(permission_provider.Pass()), |
132 service_task_runner_(service_task_runner), | 56 observer_(this), |
133 binding_(this, request.Pass()), | 57 binding_(this, request.Pass()), |
134 weak_factory_(this) { | 58 weak_factory_(this) { |
135 // This object owns itself and will be destroyed if either the message pipe | 59 // This object owns itself and will be destroyed if either the message pipe |
136 // it is bound to is closed or the PermissionProvider it depends on is | 60 // it is bound to is closed or the PermissionProvider it depends on is |
137 // unavailable. | 61 // unavailable. |
138 binding_.set_connection_error_handler([this]() { delete this; }); | 62 binding_.set_connection_error_handler([this]() { delete this; }); |
139 permission_provider_.set_connection_error_handler([this]() { delete this; }); | 63 permission_provider_.set_connection_error_handler([this]() { delete this; }); |
140 | 64 |
141 scoped_ptr<ServiceThreadHelper> helper(new ServiceThreadHelper( | 65 DCHECK(DeviceClient::Get()); |
142 weak_factory_.GetWeakPtr(), base::ThreadTaskRunnerHandle::Get())); | 66 usb_service_ = DeviceClient::Get()->GetUsbService(); |
143 helper_ = helper.get(); | 67 if (usb_service_) |
144 service_task_runner_->PostTask( | 68 observer_.Add(usb_service_); |
145 FROM_HERE, | |
146 base::Bind(&ServiceThreadHelper::Start, base::Passed(&helper))); | |
147 } | 69 } |
148 | 70 |
149 DeviceManagerImpl::~DeviceManagerImpl() { | 71 DeviceManagerImpl::~DeviceManagerImpl() { |
150 // It is safe to call this if |helper_| was already destroyed when | |
151 // |service_task_runner_| exited as the task will never execute. | |
152 service_task_runner_->DeleteSoon(FROM_HERE, helper_); | |
153 connection_error_handler_.Run(); | 72 connection_error_handler_.Run(); |
154 } | 73 } |
155 | 74 |
156 void DeviceManagerImpl::GetDevices(EnumerationOptionsPtr options, | 75 void DeviceManagerImpl::GetDevices(EnumerationOptionsPtr options, |
157 const GetDevicesCallback& callback) { | 76 const GetDevicesCallback& callback) { |
158 auto get_devices_callback = | 77 if (!usb_service_) { |
159 base::Bind(&DeviceManagerImpl::OnGetDevices, weak_factory_.GetWeakPtr(), | 78 mojo::Array<DeviceInfoPtr> no_devices; |
160 base::Passed(&options), callback); | 79 callback.Run(no_devices.Pass()); |
161 service_task_runner_->PostTask( | 80 return; |
162 FROM_HERE, base::Bind(&GetDevicesOnServiceThread, get_devices_callback, | 81 } |
163 base::ThreadTaskRunnerHandle::Get())); | 82 |
| 83 usb_service_->GetDevices(base::Bind(&DeviceManagerImpl::OnGetDevices, |
| 84 weak_factory_.GetWeakPtr(), |
| 85 base::Passed(&options), callback)); |
164 } | 86 } |
165 | 87 |
166 void DeviceManagerImpl::GetDeviceChanges( | 88 void DeviceManagerImpl::GetDeviceChanges( |
167 const GetDeviceChangesCallback& callback) { | 89 const GetDeviceChangesCallback& callback) { |
168 device_change_callbacks_.push(callback); | 90 device_change_callbacks_.push(callback); |
169 MaybeRunDeviceChangesCallback(); | 91 MaybeRunDeviceChangesCallback(); |
170 } | 92 } |
171 | 93 |
172 void DeviceManagerImpl::GetDevice( | 94 void DeviceManagerImpl::GetDevice( |
173 const mojo::String& guid, | 95 const mojo::String& guid, |
174 mojo::InterfaceRequest<Device> device_request) { | 96 mojo::InterfaceRequest<Device> device_request) { |
175 auto get_device_callback = | 97 if (!usb_service_) |
176 base::Bind(&DeviceManagerImpl::OnGetDevice, weak_factory_.GetWeakPtr(), | 98 return; |
177 base::Passed(&device_request)); | |
178 service_task_runner_->PostTask( | |
179 FROM_HERE, | |
180 base::Bind(&GetDeviceOnServiceThread, guid, get_device_callback, | |
181 base::ThreadTaskRunnerHandle::Get())); | |
182 } | |
183 | 99 |
184 void DeviceManagerImpl::OnGetDevice( | 100 scoped_refptr<UsbDevice> device = usb_service_->GetDevice(guid); |
185 mojo::InterfaceRequest<Device> device_request, | |
186 scoped_refptr<UsbDevice> device) { | |
187 if (!device) | 101 if (!device) |
188 return; | 102 return; |
189 | 103 |
190 mojo::Array<DeviceInfoPtr> requested_devices(1); | 104 mojo::Array<DeviceInfoPtr> requested_devices(1); |
191 requested_devices[0] = DeviceInfo::From(*device); | 105 requested_devices[0] = DeviceInfo::From(*device); |
192 permission_provider_->HasDevicePermission( | 106 permission_provider_->HasDevicePermission( |
193 requested_devices.Pass(), | 107 requested_devices.Pass(), |
194 base::Bind(&DeviceManagerImpl::OnGetDevicePermissionCheckComplete, | 108 base::Bind(&DeviceManagerImpl::OnGetDevicePermissionCheckComplete, |
195 base::Unretained(this), device, | 109 base::Unretained(this), device, |
196 base::Passed(&device_request))); | 110 base::Passed(&device_request))); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 devices_added_[device->guid()] = device; | 149 devices_added_[device->guid()] = device; |
236 MaybeRunDeviceChangesCallback(); | 150 MaybeRunDeviceChangesCallback(); |
237 } | 151 } |
238 | 152 |
239 void DeviceManagerImpl::OnDeviceRemoved(scoped_refptr<UsbDevice> device) { | 153 void DeviceManagerImpl::OnDeviceRemoved(scoped_refptr<UsbDevice> device) { |
240 if (devices_added_.erase(device->guid()) == 0) | 154 if (devices_added_.erase(device->guid()) == 0) |
241 devices_removed_[device->guid()] = device; | 155 devices_removed_[device->guid()] = device; |
242 MaybeRunDeviceChangesCallback(); | 156 MaybeRunDeviceChangesCallback(); |
243 } | 157 } |
244 | 158 |
| 159 void DeviceManagerImpl::WillDestroyUsbService() { |
| 160 observer_.RemoveAll(); |
| 161 usb_service_ = nullptr; |
| 162 } |
| 163 |
245 void DeviceManagerImpl::MaybeRunDeviceChangesCallback() { | 164 void DeviceManagerImpl::MaybeRunDeviceChangesCallback() { |
246 if (!permission_request_pending_ && !device_change_callbacks_.empty()) { | 165 if (!permission_request_pending_ && !device_change_callbacks_.empty()) { |
247 DeviceMap devices_added; | 166 DeviceMap devices_added; |
248 devices_added.swap(devices_added_); | 167 devices_added.swap(devices_added_); |
249 DeviceMap devices_removed; | 168 DeviceMap devices_removed; |
250 devices_removed.swap(devices_removed_); | 169 devices_removed.swap(devices_removed_); |
251 | 170 |
252 mojo::Array<DeviceInfoPtr> requested_devices(devices_added.size() + | 171 mojo::Array<DeviceInfoPtr> requested_devices(devices_added.size() + |
253 devices_removed.size()); | 172 devices_removed.size()); |
254 { | 173 { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 callback.Run(notification.Pass()); | 215 callback.Run(notification.Pass()); |
297 device_change_callbacks_.pop(); | 216 device_change_callbacks_.pop(); |
298 } | 217 } |
299 | 218 |
300 if (devices_added_.size() > 0 || !devices_removed_.empty()) | 219 if (devices_added_.size() > 0 || !devices_removed_.empty()) |
301 MaybeRunDeviceChangesCallback(); | 220 MaybeRunDeviceChangesCallback(); |
302 } | 221 } |
303 | 222 |
304 } // namespace usb | 223 } // namespace usb |
305 } // namespace device | 224 } // namespace device |
OLD | NEW |