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 |