OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "content/renderer/usb/web_usb_client_impl.h" | |
6 | |
7 #include <stddef.h> | |
8 #include <utility> | |
9 | |
10 #include "base/bind.h" | |
11 #include "base/callback.h" | |
12 #include "base/memory/scoped_ptr.h" | |
13 #include "base/move.h" | |
14 #include "base/strings/utf_string_conversions.h" | |
15 #include "content/child/mojo/type_converters.h" | |
16 #include "content/child/scoped_web_callbacks.h" | |
17 #include "content/public/common/service_registry.h" | |
18 #include "content/renderer/usb/type_converters.h" | |
19 #include "content/renderer/usb/web_usb_device_impl.h" | |
20 #include "mojo/public/cpp/bindings/array.h" | |
21 #include "mojo/public/cpp/bindings/interface_request.h" | |
22 #include "third_party/WebKit/public/platform/WebCallbacks.h" | |
23 #include "third_party/WebKit/public/platform/WebPassOwnPtr.h" | |
24 #include "third_party/WebKit/public/platform/modules/webusb/WebUSBDeviceFilter.h
" | |
25 #include "third_party/WebKit/public/platform/modules/webusb/WebUSBDeviceInfo.h" | |
26 #include "third_party/WebKit/public/platform/modules/webusb/WebUSBDeviceRequestO
ptions.h" | |
27 #include "third_party/WebKit/public/platform/modules/webusb/WebUSBError.h" | |
28 | |
29 namespace content { | |
30 | |
31 namespace { | |
32 | |
33 const char kNoServiceError[] = "USB service unavailable."; | |
34 | |
35 // Generic default rejection handler for any WebUSB callbacks type. Assumes | |
36 // |CallbacksType| is a blink::WebCallbacks<T, const blink::WebUSBError&> | |
37 // for any type |T|. | |
38 template <typename CallbacksType> | |
39 void RejectCallbacksWithError(const blink::WebUSBError& error, | |
40 scoped_ptr<CallbacksType> callbacks) { | |
41 callbacks->onError(error); | |
42 } | |
43 | |
44 // Create a new ScopedWebCallbacks for WebUSB client callbacks, defaulting to | |
45 // a "no service" rejection. | |
46 template <typename CallbacksType> | |
47 ScopedWebCallbacks<CallbacksType> MakeScopedUSBCallbacks( | |
48 CallbacksType* callbacks) { | |
49 return make_scoped_web_callbacks( | |
50 callbacks, | |
51 base::Bind(&RejectCallbacksWithError<CallbacksType>, | |
52 blink::WebUSBError(blink::WebUSBError::Error::NotFound, | |
53 base::ASCIIToUTF16(kNoServiceError)))); | |
54 } | |
55 | |
56 void OnGetDevicesComplete( | |
57 ScopedWebCallbacks<blink::WebUSBClientGetDevicesCallbacks> scoped_callbacks, | |
58 device::usb::DeviceManager* device_manager, | |
59 mojo::Array<device::usb::DeviceInfoPtr> results) { | |
60 blink::WebVector<blink::WebUSBDevice*>* devices = | |
61 new blink::WebVector<blink::WebUSBDevice*>(results.size()); | |
62 for (size_t i = 0; i < results.size(); ++i) { | |
63 device::usb::DevicePtr device; | |
64 device_manager->GetDevice(results[i]->guid, mojo::GetProxy(&device)); | |
65 (*devices)[i] = new WebUSBDeviceImpl( | |
66 std::move(device), | |
67 mojo::ConvertTo<blink::WebUSBDeviceInfo>(results[i])); | |
68 } | |
69 scoped_callbacks.PassCallbacks()->onSuccess(blink::adoptWebPtr(devices)); | |
70 } | |
71 | |
72 void OnRequestDevicesComplete( | |
73 ScopedWebCallbacks<blink::WebUSBClientRequestDeviceCallbacks> callbacks, | |
74 device::usb::DeviceManager* device_manager, | |
75 device::usb::DeviceInfoPtr result) { | |
76 auto scoped_callbacks = callbacks.PassCallbacks(); | |
77 if (result) { | |
78 device::usb::DevicePtr device; | |
79 device_manager->GetDevice(result->guid, mojo::GetProxy(&device)); | |
80 blink::WebUSBDevice* web_usb_device = new WebUSBDeviceImpl( | |
81 std::move(device), mojo::ConvertTo<blink::WebUSBDeviceInfo>(result)); | |
82 | |
83 scoped_callbacks->onSuccess(blink::adoptWebPtr(web_usb_device)); | |
84 } else { | |
85 scoped_callbacks->onError( | |
86 blink::WebUSBError(blink::WebUSBError::Error::NotFound, | |
87 base::ASCIIToUTF16("No device selected."))); | |
88 } | |
89 } | |
90 | |
91 } // namespace | |
92 | |
93 WebUSBClientImpl::WebUSBClientImpl(content::ServiceRegistry* service_registry) | |
94 : service_registry_(service_registry) {} | |
95 | |
96 WebUSBClientImpl::~WebUSBClientImpl() {} | |
97 | |
98 void WebUSBClientImpl::getDevices( | |
99 blink::WebUSBClientGetDevicesCallbacks* callbacks) { | |
100 auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks); | |
101 GetDeviceManager()->GetDevices( | |
102 nullptr, | |
103 base::Bind(&OnGetDevicesComplete, base::Passed(&scoped_callbacks), | |
104 base::Unretained(device_manager_.get()))); | |
105 } | |
106 | |
107 void WebUSBClientImpl::requestDevice( | |
108 const blink::WebUSBDeviceRequestOptions& options, | |
109 blink::WebUSBClientRequestDeviceCallbacks* callbacks) { | |
110 if (!chooser_service_) { | |
111 service_registry_->ConnectToRemoteService( | |
112 mojo::GetProxy(&chooser_service_)); | |
113 } | |
114 | |
115 auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks); | |
116 | |
117 mojo::Array<device::usb::DeviceFilterPtr> device_filters = | |
118 mojo::Array<device::usb::DeviceFilterPtr>::From(options.filters); | |
119 | |
120 chooser_service_->GetPermission( | |
121 std::move(device_filters), | |
122 base::Bind(&OnRequestDevicesComplete, base::Passed(&scoped_callbacks), | |
123 base::Unretained(device_manager_.get()))); | |
124 } | |
125 | |
126 void WebUSBClientImpl::addObserver(Observer* observer) { | |
127 if (observers_.empty()) { | |
128 // Set up two sequential calls to GetDeviceChanges to avoid latency. | |
129 device::usb::DeviceManager* device_manager = GetDeviceManager(); | |
130 device_manager->GetDeviceChanges(base::Bind( | |
131 &WebUSBClientImpl::OnDeviceChangeNotification, base::Unretained(this))); | |
132 device_manager->GetDeviceChanges(base::Bind( | |
133 &WebUSBClientImpl::OnDeviceChangeNotification, base::Unretained(this))); | |
134 } | |
135 | |
136 observers_.insert(observer); | |
137 } | |
138 | |
139 void WebUSBClientImpl::removeObserver(Observer* observer) { | |
140 DCHECK(ContainsKey(observers_, observer)); | |
141 observers_.erase(observer); | |
142 } | |
143 | |
144 device::usb::DeviceManager* WebUSBClientImpl::GetDeviceManager() { | |
145 if (!device_manager_) | |
146 service_registry_->ConnectToRemoteService(mojo::GetProxy(&device_manager_)); | |
147 return device_manager_.get(); | |
148 } | |
149 | |
150 void WebUSBClientImpl::OnDeviceChangeNotification( | |
151 device::usb::DeviceChangeNotificationPtr notification) { | |
152 if (observers_.empty()) | |
153 return; | |
154 | |
155 device_manager_->GetDeviceChanges(base::Bind( | |
156 &WebUSBClientImpl::OnDeviceChangeNotification, base::Unretained(this))); | |
157 for (size_t i = 0; i < notification->devices_added.size(); ++i) { | |
158 const device::usb::DeviceInfoPtr& device_info = | |
159 notification->devices_added[i]; | |
160 for (auto observer : observers_) { | |
161 device::usb::DevicePtr device; | |
162 device_manager_->GetDevice(device_info->guid, mojo::GetProxy(&device)); | |
163 observer->onDeviceConnected(blink::adoptWebPtr(new WebUSBDeviceImpl( | |
164 std::move(device), | |
165 mojo::ConvertTo<blink::WebUSBDeviceInfo>(device_info)))); | |
166 } | |
167 } | |
168 for (size_t i = 0; i < notification->devices_removed.size(); ++i) { | |
169 const device::usb::DeviceInfoPtr& device_info = | |
170 notification->devices_removed[i]; | |
171 for (auto observer : observers_) | |
172 observer->onDeviceDisconnected(blink::adoptWebPtr(new WebUSBDeviceImpl( | |
173 nullptr, mojo::ConvertTo<blink::WebUSBDeviceInfo>(device_info)))); | |
174 } | |
175 } | |
176 | |
177 } // namespace content | |
OLD | NEW |