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

Side by Side Diff: content/renderer/usb/web_usb_device_impl.cc

Issue 1850023002: Consume Mojo services directly in Blink's WebUSB implementation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 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
(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_device_impl.h"
6
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "content/child/mojo/type_converters.h"
13 #include "content/child/scoped_web_callbacks.h"
14 #include "content/renderer/usb/type_converters.h"
15 #include "mojo/shell/public/cpp/connect.h"
16 #include "mojo/shell/public/interfaces/connector.mojom.h"
17 #include "third_party/WebKit/public/platform/WebVector.h"
18 #include "third_party/WebKit/public/platform/modules/webusb/WebUSBDeviceInfo.h"
19 #include "third_party/WebKit/public/platform/modules/webusb/WebUSBTransferInfo.h "
20
21 namespace content {
22
23 namespace {
24
25 const char kClaimInterfaceFailed[] = "Unable to claim interface.";
26 const char kClearHaltFailed[] = "Unable to clear endpoint.";
27 const char kDeviceAlreadyOpen[] = "Device has already been opened.";
28 const char kDeviceNoAccess[] = "Access denied.";
29 const char kDeviceUnavailable[] = "Device unavailable.";
30 const char kDeviceResetFailed[] = "Unable to reset the device.";
31 const char kReleaseInterfaceFailed[] = "Unable to release interface.";
32 const char kSetConfigurationFailed[] = "Unable to set device configuration.";
33 const char kSetInterfaceFailed[] = "Unable to set device interface.";
34 const char kTransferFailed[] = "Transfer failed.";
35
36 // Generic default rejection handler for any WebUSB callbacks type. Assumes
37 // |CallbacksType| is a blink::WebCallbacks<T, const blink::WebUSBError&>
38 // for any type |T|.
39 template <typename CallbacksType>
40 void RejectWithError(const blink::WebUSBError& error,
41 scoped_ptr<CallbacksType> callbacks) {
42 callbacks->onError(error);
43 }
44
45 template <typename CallbacksType>
46 void RejectWithTransferError(scoped_ptr<CallbacksType> callbacks) {
47 RejectWithError(blink::WebUSBError(blink::WebUSBError::Error::Network,
48 base::ASCIIToUTF16(kTransferFailed)),
49 std::move(callbacks));
50 }
51
52 // Create a new ScopedWebCallbacks for WebUSB device callbacks, defaulting to
53 // a "device unavailable" rejection.
54 template <typename CallbacksType>
55 ScopedWebCallbacks<CallbacksType> MakeScopedUSBCallbacks(
56 CallbacksType* callbacks) {
57 return make_scoped_web_callbacks(
58 callbacks,
59 base::Bind(&RejectWithError<CallbacksType>,
60 blink::WebUSBError(blink::WebUSBError::Error::NotFound,
61 base::ASCIIToUTF16(kDeviceUnavailable))));
62 }
63
64 void OnOpenDevice(
65 ScopedWebCallbacks<blink::WebUSBDeviceOpenCallbacks> callbacks,
66 device::usb::OpenDeviceError error) {
67 auto scoped_callbacks = callbacks.PassCallbacks();
68 switch(error) {
69 case device::usb::OpenDeviceError::OK:
70 scoped_callbacks->onSuccess();
71 break;
72 case device::usb::OpenDeviceError::ACCESS_DENIED:
73 scoped_callbacks->onError(blink::WebUSBError(
74 blink::WebUSBError::Error::Security,
75 base::ASCIIToUTF16(kDeviceNoAccess)));
76 break;
77 case device::usb::OpenDeviceError::ALREADY_OPEN:
78 scoped_callbacks->onError(blink::WebUSBError(
79 blink::WebUSBError::Error::InvalidState,
80 base::ASCIIToUTF16(kDeviceAlreadyOpen)));
81 break;
82 default:
83 NOTREACHED();
84 }
85 }
86
87 void OnDeviceClosed(
88 ScopedWebCallbacks<blink::WebUSBDeviceCloseCallbacks> callbacks) {
89 callbacks.PassCallbacks()->onSuccess();
90 }
91
92 void HandlePassFailDeviceOperation(
93 ScopedWebCallbacks<blink::WebCallbacks<void, const blink::WebUSBError&>>
94 callbacks,
95 const std::string& failure_message,
96 bool success) {
97 auto scoped_callbacks = callbacks.PassCallbacks();
98 if (success) {
99 scoped_callbacks->onSuccess();
100 } else {
101 RejectWithError(blink::WebUSBError(blink::WebUSBError::Error::Network,
102 base::ASCIIToUTF16(failure_message)),
103 std::move(scoped_callbacks));
104 }
105 }
106
107 void OnTransferIn(
108 ScopedWebCallbacks<blink::WebUSBDeviceTransferCallbacks> callbacks,
109 device::usb::TransferStatus status,
110 mojo::Array<uint8_t> data) {
111 auto scoped_callbacks = callbacks.PassCallbacks();
112 blink::WebUSBTransferInfo::Status web_status;
113 switch (status) {
114 case device::usb::TransferStatus::COMPLETED:
115 web_status = blink::WebUSBTransferInfo::Status::Ok;
116 break;
117 case device::usb::TransferStatus::STALLED:
118 web_status = blink::WebUSBTransferInfo::Status::Stall;
119 break;
120 case device::usb::TransferStatus::BABBLE:
121 web_status = blink::WebUSBTransferInfo::Status::Babble;
122 break;
123 default:
124 RejectWithTransferError(std::move(scoped_callbacks));
125 return;
126 }
127 scoped_ptr<blink::WebUSBTransferInfo> info(new blink::WebUSBTransferInfo());
128 info->status.assign(
129 std::vector<blink::WebUSBTransferInfo::Status>(1, web_status));
130 info->data.assign(data);
131 scoped_callbacks->onSuccess(adoptWebPtr(info.release()));
132 }
133
134 void OnTransferOut(
135 ScopedWebCallbacks<blink::WebUSBDeviceTransferCallbacks> callbacks,
136 size_t bytes_written,
137 device::usb::TransferStatus status) {
138 auto scoped_callbacks = callbacks.PassCallbacks();
139 blink::WebUSBTransferInfo::Status web_status;
140 switch (status) {
141 case device::usb::TransferStatus::COMPLETED:
142 web_status = blink::WebUSBTransferInfo::Status::Ok;
143 break;
144 case device::usb::TransferStatus::STALLED:
145 web_status = blink::WebUSBTransferInfo::Status::Stall;
146 break;
147 default:
148 RejectWithTransferError(std::move(scoped_callbacks));
149 return;
150 }
151 // TODO(rockot): Device::ControlTransferOut should expose the number of bytes
152 // actually transferred so we can send it from here.
153 scoped_ptr<blink::WebUSBTransferInfo> info(new blink::WebUSBTransferInfo());
154 info->status.assign(
155 std::vector<blink::WebUSBTransferInfo::Status>(1, web_status));
156 info->bytesTransferred.assign(std::vector<uint32_t>(1, bytes_written));
157 scoped_callbacks->onSuccess(adoptWebPtr(info.release()));
158 }
159
160 void OnIsochronousTransferIn(
161 ScopedWebCallbacks<blink::WebUSBDeviceTransferCallbacks> callbacks,
162 mojo::Array<uint8_t> data,
163 mojo::Array<device::usb::IsochronousPacketPtr> packets) {
164 auto scoped_callbacks = callbacks.PassCallbacks();
165 scoped_ptr<blink::WebUSBTransferInfo> info(new blink::WebUSBTransferInfo());
166 info->data.assign(data);
167 info->status =
168 blink::WebVector<blink::WebUSBTransferInfo::Status>(packets.size());
169 info->packetLength = blink::WebVector<uint32_t>(packets.size());
170 info->bytesTransferred = blink::WebVector<uint32_t>(packets.size());
171 for (size_t i = 0; i < packets.size(); ++i) {
172 switch (packets[i]->status) {
173 case device::usb::TransferStatus::COMPLETED:
174 info->status[i] = blink::WebUSBTransferInfo::Status::Ok;
175 break;
176 case device::usb::TransferStatus::STALLED:
177 info->status[i] = blink::WebUSBTransferInfo::Status::Stall;
178 break;
179 case device::usb::TransferStatus::BABBLE:
180 info->status[i] = blink::WebUSBTransferInfo::Status::Babble;
181 break;
182 default:
183 RejectWithTransferError(std::move(scoped_callbacks));
184 return;
185 }
186 info->packetLength[i] = packets[i]->length;
187 info->bytesTransferred[i] = packets[i]->transferred_length;
188 }
189 scoped_callbacks->onSuccess(adoptWebPtr(info.release()));
190 }
191
192 void OnIsochronousTransferOut(
193 ScopedWebCallbacks<blink::WebUSBDeviceTransferCallbacks> callbacks,
194 mojo::Array<device::usb::IsochronousPacketPtr> packets) {
195 auto scoped_callbacks = callbacks.PassCallbacks();
196 scoped_ptr<blink::WebUSBTransferInfo> info(new blink::WebUSBTransferInfo());
197 info->status =
198 blink::WebVector<blink::WebUSBTransferInfo::Status>(packets.size());
199 info->bytesTransferred = blink::WebVector<uint32_t>(packets.size());
200 for (size_t i = 0; i < packets.size(); ++i) {
201 switch (packets[i]->status) {
202 case device::usb::TransferStatus::COMPLETED:
203 info->status[i] = blink::WebUSBTransferInfo::Status::Ok;
204 break;
205 case device::usb::TransferStatus::STALLED:
206 info->status[i] = blink::WebUSBTransferInfo::Status::Stall;
207 break;
208 default:
209 RejectWithTransferError(std::move(scoped_callbacks));
210 return;
211 }
212 info->bytesTransferred[i] = packets[i]->transferred_length;
213 }
214 scoped_callbacks->onSuccess(adoptWebPtr(info.release()));
215 }
216
217 } // namespace
218
219 WebUSBDeviceImpl::WebUSBDeviceImpl(device::usb::DevicePtr device,
220 const blink::WebUSBDeviceInfo& device_info)
221 : device_(std::move(device)),
222 device_info_(device_info),
223 weak_factory_(this) {
224 if (device_)
225 device_.set_connection_error_handler([this]() { device_.reset(); });
226 }
227
228 WebUSBDeviceImpl::~WebUSBDeviceImpl() {}
229
230 const blink::WebUSBDeviceInfo& WebUSBDeviceImpl::info() const {
231 return device_info_;
232 }
233
234 void WebUSBDeviceImpl::open(blink::WebUSBDeviceOpenCallbacks* callbacks) {
235 auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
236 if (device_)
237 device_->Open(base::Bind(&OnOpenDevice, base::Passed(&scoped_callbacks)));
238 }
239
240 void WebUSBDeviceImpl::close(blink::WebUSBDeviceCloseCallbacks* callbacks) {
241 auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
242 if (device_)
243 device_->Close(
244 base::Bind(&OnDeviceClosed, base::Passed(&scoped_callbacks)));
245 }
246
247 void WebUSBDeviceImpl::setConfiguration(
248 uint8_t configuration_value,
249 blink::WebUSBDeviceSetConfigurationCallbacks* callbacks) {
250 auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
251 if (device_)
252 device_->SetConfiguration(
253 configuration_value,
254 base::Bind(&HandlePassFailDeviceOperation,
255 base::Passed(&scoped_callbacks), kSetConfigurationFailed));
256 }
257
258 void WebUSBDeviceImpl::claimInterface(
259 uint8_t interface_number,
260 blink::WebUSBDeviceClaimInterfaceCallbacks* callbacks) {
261 auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
262 if (device_)
263 device_->ClaimInterface(
264 interface_number,
265 base::Bind(&HandlePassFailDeviceOperation,
266 base::Passed(&scoped_callbacks), kClaimInterfaceFailed));
267 }
268
269 void WebUSBDeviceImpl::releaseInterface(
270 uint8_t interface_number,
271 blink::WebUSBDeviceReleaseInterfaceCallbacks* callbacks) {
272 auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
273 if (device_)
274 device_->ReleaseInterface(
275 interface_number,
276 base::Bind(&HandlePassFailDeviceOperation,
277 base::Passed(&scoped_callbacks), kReleaseInterfaceFailed));
278 }
279
280 void WebUSBDeviceImpl::setInterface(
281 uint8_t interface_number,
282 uint8_t alternate_setting,
283 blink::WebUSBDeviceSetInterfaceAlternateSettingCallbacks* callbacks) {
284 auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
285 if (device_)
286 device_->SetInterfaceAlternateSetting(
287 interface_number, alternate_setting,
288 base::Bind(&HandlePassFailDeviceOperation,
289 base::Passed(&scoped_callbacks), kSetInterfaceFailed));
290 }
291
292 void WebUSBDeviceImpl::clearHalt(
293 uint8_t endpoint_number,
294 blink::WebUSBDeviceClearHaltCallbacks* callbacks) {
295 auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
296 if (device_)
297 device_->ClearHalt(
298 endpoint_number,
299 base::Bind(&HandlePassFailDeviceOperation,
300 base::Passed(&scoped_callbacks), kClearHaltFailed));
301 }
302
303 void WebUSBDeviceImpl::controlTransfer(
304 const blink::WebUSBDevice::ControlTransferParameters& parameters,
305 uint8_t* data,
306 size_t data_size,
307 unsigned int timeout,
308 blink::WebUSBDeviceTransferCallbacks* callbacks) {
309 auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
310 if (!device_)
311 return;
312
313 device::usb::ControlTransferParamsPtr params =
314 device::usb::ControlTransferParams::From(parameters);
315 switch (parameters.direction) {
316 case WebUSBDevice::TransferDirection::In:
317 device_->ControlTransferIn(
318 std::move(params), data_size, timeout,
319 base::Bind(&OnTransferIn, base::Passed(&scoped_callbacks)));
320 break;
321 case WebUSBDevice::TransferDirection::Out: {
322 std::vector<uint8_t> bytes;
323 if (data)
324 bytes.assign(data, data + data_size);
325 mojo::Array<uint8_t> mojo_bytes;
326 mojo_bytes.Swap(&bytes);
327 device_->ControlTransferOut(
328 std::move(params), std::move(mojo_bytes), timeout,
329 base::Bind(&OnTransferOut, base::Passed(&scoped_callbacks),
330 data_size));
331 break;
332 }
333 default:
334 NOTREACHED();
335 }
336 }
337
338 void WebUSBDeviceImpl::transfer(
339 blink::WebUSBDevice::TransferDirection direction,
340 uint8_t endpoint_number,
341 uint8_t* data,
342 size_t data_size,
343 unsigned int timeout,
344 blink::WebUSBDeviceTransferCallbacks* callbacks) {
345 auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
346 if (!device_)
347 return;
348
349 switch (direction) {
350 case WebUSBDevice::TransferDirection::In:
351 device_->GenericTransferIn(
352 endpoint_number, data_size, timeout,
353 base::Bind(&OnTransferIn, base::Passed(&scoped_callbacks)));
354 break;
355 case WebUSBDevice::TransferDirection::Out: {
356 std::vector<uint8_t> bytes;
357 if (data)
358 bytes.assign(data, data + data_size);
359 mojo::Array<uint8_t> mojo_bytes;
360 mojo_bytes.Swap(&bytes);
361 device_->GenericTransferOut(
362 endpoint_number, std::move(mojo_bytes), timeout,
363 base::Bind(&OnTransferOut, base::Passed(&scoped_callbacks),
364 data_size));
365 break;
366 }
367 default:
368 NOTREACHED();
369 }
370 }
371
372 void WebUSBDeviceImpl::isochronousTransfer(
373 blink::WebUSBDevice::TransferDirection direction,
374 uint8_t endpoint_number,
375 uint8_t* data,
376 size_t data_size,
377 blink::WebVector<uint32_t> packet_lengths,
378 unsigned int timeout,
379 blink::WebUSBDeviceTransferCallbacks* callbacks) {
380 auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
381 if (!device_)
382 return;
383
384 switch (direction) {
385 case WebUSBDevice::TransferDirection::In:
386 device_->IsochronousTransferIn(
387 endpoint_number, mojo::Array<uint32_t>::From(packet_lengths), timeout,
388 base::Bind(&OnIsochronousTransferIn,
389 base::Passed(&scoped_callbacks)));
390 break;
391 case WebUSBDevice::TransferDirection::Out: {
392 std::vector<uint8_t> bytes;
393 if (data)
394 bytes.assign(data, data + data_size);
395 mojo::Array<uint8_t> mojo_bytes;
396 mojo_bytes.Swap(&bytes);
397 device_->IsochronousTransferOut(
398 endpoint_number, std::move(mojo_bytes),
399 mojo::Array<uint32_t>::From(packet_lengths), timeout,
400 base::Bind(&OnIsochronousTransferOut,
401 base::Passed(&scoped_callbacks)));
402 break;
403 }
404 default:
405 NOTREACHED();
406 }
407 }
408
409 void WebUSBDeviceImpl::reset(blink::WebUSBDeviceResetCallbacks* callbacks) {
410 auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
411 if (device_)
412 device_->Reset(base::Bind(&HandlePassFailDeviceOperation,
413 base::Passed(&scoped_callbacks),
414 kDeviceResetFailed));
415 }
416
417 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698