cygprofile: increase timeouts to allow showing web contents
[chromium-blink-merge.git] / device / devices_app / usb / device_manager_impl.cc
blobf438460ddd828dae87a4c28ca2320c41c9e8660a
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
3 // found in the LICENSE file.
5 #include "device/devices_app/usb/device_manager_impl.h"
7 #include "base/bind.h"
8 #include "base/location.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"
14 #include "base/thread_task_runner_handle.h"
15 #include "device/core/device_client.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"
19 #include "device/devices_app/usb/type_converters.h"
20 #include "device/usb/usb_device.h"
21 #include "device/usb/usb_device_filter.h"
22 #include "device/usb/usb_service.h"
23 #include "third_party/mojo/src/mojo/public/cpp/bindings/array.h"
24 #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h"
26 namespace device {
27 namespace usb {
29 namespace {
31 void OnGetDevicesOnServiceThread(
32 const std::vector<UsbDeviceFilter>& filters,
33 const base::Callback<void(mojo::Array<DeviceInfoPtr>)>& callback,
34 scoped_refptr<base::TaskRunner> callback_task_runner,
35 const std::vector<scoped_refptr<UsbDevice>>& devices) {
36 mojo::Array<DeviceInfoPtr> mojo_devices(0);
37 for (size_t i = 0; i < devices.size(); ++i) {
38 if (UsbDeviceFilter::MatchesAny(devices[i], filters) || filters.empty())
39 mojo_devices.push_back(DeviceInfo::From(*devices[i]));
41 callback_task_runner->PostTask(
42 FROM_HERE, base::Bind(callback, base::Passed(&mojo_devices)));
45 void GetDevicesOnServiceThread(
46 const std::vector<UsbDeviceFilter>& filters,
47 const base::Callback<void(mojo::Array<DeviceInfoPtr>)>& callback,
48 scoped_refptr<base::TaskRunner> callback_task_runner) {
49 DCHECK(DeviceClient::Get());
50 UsbService* usb_service = DeviceClient::Get()->GetUsbService();
51 if (!usb_service) {
52 mojo::Array<DeviceInfoPtr> no_devices(0);
53 callback_task_runner->PostTask(
54 FROM_HERE, base::Bind(callback, base::Passed(&no_devices)));
55 return;
57 usb_service->GetDevices(base::Bind(&OnGetDevicesOnServiceThread, filters,
58 callback, callback_task_runner));
61 void RunOpenDeviceCallback(const DeviceManager::OpenDeviceCallback& callback,
62 OpenDeviceError error) {
63 callback.Run(error);
66 void OnOpenDeviceOnServiceThread(
67 mojo::InterfaceRequest<Device> device_request,
68 const DeviceManager::OpenDeviceCallback& callback,
69 scoped_refptr<base::TaskRunner> callback_task_runner,
70 scoped_refptr<UsbDeviceHandle> device_handle) {
71 if (!device_handle) {
72 callback_task_runner->PostTask(FROM_HERE,
73 base::Bind(&RunOpenDeviceCallback, callback,
74 OPEN_DEVICE_ERROR_ACCESS_DENIED));
75 return;
78 // Owned by its MessagePipe.
79 new DeviceImpl(device_handle, device_request.Pass());
81 callback_task_runner->PostTask(
82 FROM_HERE,
83 base::Bind(&RunOpenDeviceCallback, callback, OPEN_DEVICE_ERROR_OK));
86 void OpenDeviceOnServiceThread(
87 const std::string& guid,
88 mojo::InterfaceRequest<Device> device_request,
89 const DeviceManager::OpenDeviceCallback& callback,
90 scoped_refptr<base::TaskRunner> callback_task_runner) {
91 DCHECK(DeviceClient::Get());
92 UsbService* usb_service = DeviceClient::Get()->GetUsbService();
93 if (!usb_service) {
94 callback_task_runner->PostTask(FROM_HERE,
95 base::Bind(&RunOpenDeviceCallback, callback,
96 OPEN_DEVICE_ERROR_NOT_FOUND));
97 return;
99 scoped_refptr<UsbDevice> device = usb_service->GetDevice(guid);
100 if (!device) {
101 callback_task_runner->PostTask(FROM_HERE,
102 base::Bind(&RunOpenDeviceCallback, callback,
103 OPEN_DEVICE_ERROR_NOT_FOUND));
104 return;
106 device->Open(base::Bind(&OnOpenDeviceOnServiceThread,
107 base::Passed(&device_request), callback,
108 callback_task_runner));
111 } // namespace
113 class DeviceManagerImpl::ServiceThreadHelper
114 : public UsbService::Observer,
115 public base::MessageLoop::DestructionObserver {
116 public:
117 ServiceThreadHelper(base::WeakPtr<DeviceManagerImpl> manager,
118 scoped_refptr<base::TaskRunner> task_runner)
119 : observer_(this), manager_(manager), task_runner_(task_runner) {}
121 ~ServiceThreadHelper() override {
122 base::MessageLoop::current()->RemoveDestructionObserver(this);
125 static void Start(
126 scoped_ptr<ServiceThreadHelper> self,
127 const base::Callback<void(mojo::Array<DeviceInfoPtr>)>& callback) {
128 UsbService* usb_service = DeviceClient::Get()->GetUsbService();
129 if (usb_service) {
130 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_));
137 // |self| now owned by the current message loop.
138 base::MessageLoop::current()->AddDestructionObserver(self.release());
141 private:
142 // UsbService::Observer
143 void OnDeviceAdded(scoped_refptr<UsbDevice> device) override {
144 DeviceInfoPtr mojo_device(DeviceInfo::From(*device));
145 task_runner_->PostTask(
146 FROM_HERE, base::Bind(&DeviceManagerImpl::OnDeviceAdded, manager_,
147 base::Passed(&mojo_device)));
150 void OnDeviceRemoved(scoped_refptr<UsbDevice> device) override {
151 task_runner_->PostTask(
152 FROM_HERE, base::Bind(&DeviceManagerImpl::OnDeviceRemoved, manager_,
153 device->guid()));
156 // base::MessageLoop::DestructionObserver
157 void WillDestroyCurrentMessageLoop() override { delete this; }
159 ScopedObserver<UsbService, UsbService::Observer> observer_;
160 base::WeakPtr<DeviceManagerImpl> manager_;
161 scoped_refptr<base::TaskRunner> task_runner_;
164 DeviceManagerImpl::DeviceManagerImpl(
165 mojo::InterfaceRequest<DeviceManager> request,
166 scoped_ptr<DeviceManagerDelegate> delegate,
167 scoped_refptr<base::SequencedTaskRunner> service_task_runner)
168 : binding_(this, request.Pass()),
169 delegate_(delegate.Pass()),
170 service_task_runner_(service_task_runner),
171 weak_factory_(this) {
174 DeviceManagerImpl::~DeviceManagerImpl() {
175 if (helper_) {
176 // It is safe to call this if |helper_| was already destroyed when
177 // |service_task_runner_| exited as the task will never execute.
178 service_task_runner_->DeleteSoon(FROM_HERE, helper_);
182 void DeviceManagerImpl::set_connection_error_handler(
183 const mojo::Closure& error_handler) {
184 binding_.set_connection_error_handler(error_handler);
187 void DeviceManagerImpl::GetDevices(EnumerationOptionsPtr options,
188 const GetDevicesCallback& callback) {
189 auto filters = options->filters.To<std::vector<UsbDeviceFilter>>();
190 auto get_devices_callback = base::Bind(&DeviceManagerImpl::OnGetDevices,
191 weak_factory_.GetWeakPtr(), callback);
192 service_task_runner_->PostTask(
193 FROM_HERE,
194 base::Bind(&GetDevicesOnServiceThread, filters, get_devices_callback,
195 base::ThreadTaskRunnerHandle::Get()));
198 void DeviceManagerImpl::GetDeviceChanges(
199 const GetDeviceChangesCallback& callback) {
200 if (helper_) {
201 device_change_callbacks_.push(callback);
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));
216 void DeviceManagerImpl::OpenDevice(
217 const mojo::String& guid,
218 mojo::InterfaceRequest<Device> device_request,
219 const OpenDeviceCallback& callback) {
220 service_task_runner_->PostTask(
221 FROM_HERE, base::Bind(&OpenDeviceOnServiceThread, guid,
222 base::Passed(&device_request), callback,
223 base::ThreadTaskRunnerHandle::Get()));
226 void DeviceManagerImpl::OnGetDevices(const GetDevicesCallback& callback,
227 mojo::Array<DeviceInfoPtr> devices) {
228 mojo::Array<DeviceInfoPtr> allowed_devices(0);
229 for (size_t i = 0; i < devices.size(); ++i) {
230 if (delegate_->IsDeviceAllowed(*devices[i]))
231 allowed_devices.push_back(devices[i].Pass());
233 callback.Run(allowed_devices.Pass());
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());
246 callback.Run(notification.Pass());
249 void DeviceManagerImpl::OnDeviceAdded(DeviceInfoPtr device) {
250 DCHECK(!ContainsKey(devices_removed_, device->guid));
251 devices_added_.push_back(device.Pass());
252 MaybeRunDeviceChangesCallback();
255 void DeviceManagerImpl::OnDeviceRemoved(std::string device_guid) {
256 bool found = false;
257 mojo::Array<DeviceInfoPtr> devices_added;
258 for (size_t i = 0; i < devices_added_.size(); ++i) {
259 if (devices_added_[i]->guid == device_guid)
260 found = true;
261 else
262 devices_added.push_back(devices_added_[i].Pass());
264 devices_added.Swap(&devices_added_);
265 if (!found)
266 devices_removed_.insert(device_guid);
267 MaybeRunDeviceChangesCallback();
270 void DeviceManagerImpl::MaybeRunDeviceChangesCallback() {
271 if (!device_change_callbacks_.empty()) {
272 DeviceChangeNotificationPtr notification = DeviceChangeNotification::New();
273 notification->devices_added.Swap(&devices_added_);
274 notification->devices_removed.resize(0);
275 for (const std::string& device : devices_removed_)
276 notification->devices_removed.push_back(device);
277 devices_removed_.clear();
279 const GetDeviceChangesCallback& callback = device_change_callbacks_.front();
280 callback.Run(notification.Pass());
281 device_change_callbacks_.pop();
285 } // namespace usb
286 } // namespace device