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

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

Issue 1314493003: Implement most of WebUSB device client interface (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 4 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "content/renderer/usb/web_usb_device_impl.h" 5 #include "content/renderer/usb/web_usb_device_impl.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/callback.h" 8 #include "base/callback.h"
9 #include "base/strings/utf_string_conversions.h" 9 #include "base/strings/utf_string_conversions.h"
10 #include "content/child/scoped_web_callbacks.h"
10 #include "content/renderer/usb/type_converters.h" 11 #include "content/renderer/usb/type_converters.h"
11 #include "device/devices_app/public/cpp/constants.h" 12 #include "device/devices_app/public/cpp/constants.h"
12 #include "mojo/application/public/cpp/connect.h" 13 #include "mojo/application/public/cpp/connect.h"
13 #include "mojo/application/public/interfaces/shell.mojom.h" 14 #include "mojo/application/public/interfaces/shell.mojom.h"
14 #include "third_party/WebKit/public/platform/WebVector.h" 15 #include "third_party/WebKit/public/platform/WebVector.h"
15 #include "third_party/WebKit/public/platform/modules/webusb/WebUSBDeviceInfo.h" 16 #include "third_party/WebKit/public/platform/modules/webusb/WebUSBDeviceInfo.h"
16 #include "third_party/WebKit/public/platform/modules/webusb/WebUSBTransferInfo.h " 17 #include "third_party/WebKit/public/platform/modules/webusb/WebUSBTransferInfo.h "
17 18
18 namespace content { 19 namespace content {
19 20
20 namespace { 21 namespace {
21 22
23 const char kClaimInterfaceFailed[] = "Unable to claim interface.";
24 const char kClearHaltFailed[] = "Unable to clear endpoint.";
25 const char kDeviceNoAccess[] = "Access denied.";
26 const char kDeviceNotFound[] = "Device not found.";
27 const char kDeviceNotOpened[] = "Device not opened.";
28 const char kDeviceUnavailable[] = "Device unavailable.";
29 const char kDeviceResetFailed[] = "Unable to reset the device.";
22 const char kNotImplementedError[] = "Not implemented."; 30 const char kNotImplementedError[] = "Not implemented.";
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.";
23 35
24 template <typename ResultType> 36 // Generic default rejection handler for any WebUSB callbacks type. Assumes
25 void RejectAsNotImplemented( 37 // |CallbacksType| is a blink::WebCallbacks<T, const blink::WebUSBError&>
26 blink::WebCallbacks<ResultType, const blink::WebUSBError&>* callbacks) { 38 // for any type |T|.
27 callbacks->onError( 39 template <typename CallbacksType>
28 blink::WebUSBError(blink::WebUSBError::Error::Service, 40 void RejectWithError(const blink::WebUSBError& error,
29 base::UTF8ToUTF16(kNotImplementedError))); 41 scoped_ptr<CallbacksType> callbacks) {
30 delete callbacks; 42 callbacks->onError(error);
43 }
44
45 template <typename CallbacksType>
46 void RejectWithDeviceError(const std::string& message,
47 scoped_ptr<CallbacksType> callbacks) {
48 RejectWithError(blink::WebUSBError(blink::WebUSBError::Error::Device,
49 base::UTF8ToUTF16(message)),
50 callbacks.Pass());
51 }
52
53 template <typename CallbacksType>
54 void RejectWithTransferError(scoped_ptr<CallbacksType> callbacks) {
55 RejectWithError(blink::WebUSBError(blink::WebUSBError::Error::Transfer,
56 base::UTF8ToUTF16(kTransferFailed)),
57 callbacks.Pass());
58 }
59
60 // Create a new ScopedWebCallbacks for WebUSB device callbacks, defaulting to
61 // a "device unavailable" rejection.
62 template <typename CallbacksType>
63 ScopedWebCallbacks<CallbacksType> MakeScopedUSBCallbacks(
64 CallbacksType* callbacks) {
65 return make_scoped_web_callbacks(
66 callbacks,
67 base::Bind(&RejectWithError<CallbacksType>,
68 blink::WebUSBError(blink::WebUSBError::Error::Device,
69 base::UTF8ToUTF16(kDeviceUnavailable))));
70 }
71
72 void OnOpenDevice(
73 ScopedWebCallbacks<blink::WebUSBDeviceOpenCallbacks> callbacks,
74 device::usb::OpenDeviceError error) {
75 auto scoped_callbacks = callbacks.PassCallbacks();
76 switch(error) {
77 case device::usb::OPEN_DEVICE_ERROR_OK:
78 scoped_callbacks->onSuccess();
79 break;
80 case device::usb::OPEN_DEVICE_ERROR_NOT_FOUND:
81 scoped_callbacks->onError(blink::WebUSBError(
82 blink::WebUSBError::Error::Device,
83 base::UTF8ToUTF16(kDeviceNotFound)));
84 break;
85 case device::usb::OPEN_DEVICE_ERROR_ACCESS_DENIED:
86 scoped_callbacks->onError(blink::WebUSBError(
87 blink::WebUSBError::Error::Device,
88 base::UTF8ToUTF16(kDeviceNoAccess)));
89 break;
90 default:
91 NOTREACHED();
92 }
93 }
94
95 void OnDeviceClosed(
96 ScopedWebCallbacks<blink::WebUSBDeviceCloseCallbacks> callbacks) {
97 callbacks.PassCallbacks()->onSuccess();
98 }
99
100 void HandlePassFailDeviceOperation(
101 ScopedWebCallbacks<blink::WebCallbacks<void, const blink::WebUSBError&>>
102 callbacks,
103 const std::string& failure_message,
104 bool success) {
105 auto scoped_callbacks = callbacks.PassCallbacks();
106 if (success)
107 scoped_callbacks->onSuccess();
108 else
109 RejectWithDeviceError(failure_message, scoped_callbacks.Pass());
110 }
111
112 void OnTransferIn(
113 ScopedWebCallbacks<blink::WebUSBDeviceControlTransferCallbacks> callbacks,
114 device::usb::TransferStatus status,
115 mojo::Array<uint8_t> data) {
116 auto scoped_callbacks = callbacks.PassCallbacks();
117 if (status != device::usb::TRANSFER_STATUS_COMPLETED) {
118 RejectWithTransferError(scoped_callbacks.Pass());
119 return;
120 }
121 scoped_ptr<blink::WebUSBTransferInfo> info(new blink::WebUSBTransferInfo);
Reilly Grant (use Gerrit) 2015/08/24 21:24:15 It shouldn't matter in this case but calling const
Ken Rockot(use gerrit already) 2015/08/24 21:51:07 Fair enough. I don't really see a problem with it
122 info->status = blink::WebUSBTransferInfo::Status::Ok;
123 std::vector<uint8_t> bytes;
124 data.Swap(&bytes);
Reilly Grant (use Gerrit) 2015/08/24 21:24:15 What's the reason for swapping here? It seems like
Ken Rockot(use gerrit already) 2015/08/24 21:51:07 Oops, you're right. Done.
125 info->data.assign(bytes);
126 scoped_callbacks->onSuccess(adoptWebPtr(info.release()));
127 }
128
129 void OnTransferOut(
130 ScopedWebCallbacks<blink::WebUSBDeviceControlTransferCallbacks> callbacks,
131 size_t bytes_written,
132 device::usb::TransferStatus status) {
133 auto scoped_callbacks = callbacks.PassCallbacks();
134 scoped_ptr<blink::WebUSBTransferInfo> info(new blink::WebUSBTransferInfo);
135 switch (status) {
136 case device::usb::TRANSFER_STATUS_COMPLETED:
137 info->status = blink::WebUSBTransferInfo::Status::Ok;
138 break;
139 case device::usb::TRANSFER_STATUS_STALLED:
140 info->status = blink::WebUSBTransferInfo::Status::Stall;
141 break;
142 case device::usb::TRANSFER_STATUS_BABBLE:
143 info->status = blink::WebUSBTransferInfo::Status::Babble;
144 break;
145 default:
146 RejectWithTransferError(scoped_callbacks.Pass());
147 return;
148 }
149
150 // TODO(rockot): Device::ControlTransferOut should expose the number of bytes
151 // actually transferred so we can send it from here.
152 info->bytesWritten = bytes_written;
153 scoped_callbacks->onSuccess(adoptWebPtr(info.release()));
31 } 154 }
32 155
33 } // namespace 156 } // namespace
34 157
35 WebUSBDeviceImpl::WebUSBDeviceImpl(device::usb::DeviceManagerPtr device_manager, 158 WebUSBDeviceImpl::WebUSBDeviceImpl(device::usb::DeviceManagerPtr device_manager,
36 const blink::WebUSBDeviceInfo& device_info) 159 const blink::WebUSBDeviceInfo& device_info)
37 : device_manager_(device_manager.Pass()), 160 : device_manager_(device_manager.Pass()),
38 device_info_(device_info), 161 device_info_(device_info),
39 weak_factory_(this) {} 162 weak_factory_(this) {}
40 163
41 WebUSBDeviceImpl::~WebUSBDeviceImpl() {} 164 WebUSBDeviceImpl::~WebUSBDeviceImpl() {}
42 165
43 const blink::WebUSBDeviceInfo& WebUSBDeviceImpl::info() const { 166 const blink::WebUSBDeviceInfo& WebUSBDeviceImpl::info() const {
44 return device_info_; 167 return device_info_;
45 } 168 }
46 169
47 void WebUSBDeviceImpl::open(blink::WebUSBDeviceOpenCallbacks* callbacks) { 170 void WebUSBDeviceImpl::open(blink::WebUSBDeviceOpenCallbacks* callbacks) {
48 RejectAsNotImplemented(callbacks); 171 auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
172 device_manager_->OpenDevice(
173 device_info_.guid.utf8(),
174 mojo::GetProxy(&device_),
175 base::Bind(&OnOpenDevice, base::Passed(&scoped_callbacks)));
49 } 176 }
50 177
51 void WebUSBDeviceImpl::close(blink::WebUSBDeviceCloseCallbacks* callbacks) { 178 void WebUSBDeviceImpl::close(blink::WebUSBDeviceCloseCallbacks* callbacks) {
52 RejectAsNotImplemented(callbacks); 179 auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
180 if (!device_) {
181 RejectWithDeviceError(kDeviceNotOpened, scoped_callbacks.PassCallbacks());
182 } else {
183 device_->Close(
184 base::Bind(&OnDeviceClosed, base::Passed(&scoped_callbacks)));
185 }
53 } 186 }
54 187
55 void WebUSBDeviceImpl::setConfiguration( 188 void WebUSBDeviceImpl::setConfiguration(
56 uint8_t configuration_value, 189 uint8_t configuration_value,
57 blink::WebUSBDeviceSetConfigurationCallbacks* callbacks) { 190 blink::WebUSBDeviceSetConfigurationCallbacks* callbacks) {
58 RejectAsNotImplemented(callbacks); 191 auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
192 if (!device_) {
193 RejectWithDeviceError(kDeviceNotOpened, scoped_callbacks.PassCallbacks());
194 } else {
195 device_->SetConfiguration(
196 configuration_value,
197 base::Bind(&HandlePassFailDeviceOperation,
198 base::Passed(&scoped_callbacks), kSetConfigurationFailed));
199 }
59 } 200 }
60 201
61 void WebUSBDeviceImpl::claimInterface( 202 void WebUSBDeviceImpl::claimInterface(
62 uint8_t interface_number, 203 uint8_t interface_number,
63 blink::WebUSBDeviceClaimInterfaceCallbacks* callbacks) { 204 blink::WebUSBDeviceClaimInterfaceCallbacks* callbacks) {
64 RejectAsNotImplemented(callbacks); 205 auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
206 if (!device_) {
207 RejectWithDeviceError(kDeviceNotOpened, scoped_callbacks.PassCallbacks());
208 } else {
209 device_->ClaimInterface(
210 interface_number,
211 base::Bind(&HandlePassFailDeviceOperation,
212 base::Passed(&scoped_callbacks), kClaimInterfaceFailed));
213 }
65 } 214 }
66 215
67 void WebUSBDeviceImpl::releaseInterface( 216 void WebUSBDeviceImpl::releaseInterface(
68 uint8_t interface_number, 217 uint8_t interface_number,
69 blink::WebUSBDeviceReleaseInterfaceCallbacks* callbacks) { 218 blink::WebUSBDeviceReleaseInterfaceCallbacks* callbacks) {
70 RejectAsNotImplemented(callbacks); 219 auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
220 if (!device_) {
221 RejectWithDeviceError(kDeviceNotOpened, scoped_callbacks.PassCallbacks());
222 } else {
223 device_->ReleaseInterface(
224 interface_number,
225 base::Bind(&HandlePassFailDeviceOperation,
226 base::Passed(&scoped_callbacks), kReleaseInterfaceFailed));
227 }
71 } 228 }
72 229
73 void WebUSBDeviceImpl::setInterface( 230 void WebUSBDeviceImpl::setInterface(
74 uint8_t interface_number, 231 uint8_t interface_number,
75 uint8_t alternate_setting, 232 uint8_t alternate_setting,
76 blink::WebUSBDeviceSetInterfaceAlternateSettingCallbacks* callbacks) { 233 blink::WebUSBDeviceSetInterfaceAlternateSettingCallbacks* callbacks) {
77 RejectAsNotImplemented(callbacks); 234 auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
235 if (!device_) {
236 RejectWithDeviceError(kDeviceNotOpened, scoped_callbacks.PassCallbacks());
237 } else {
238 device_->SetInterfaceAlternateSetting(
239 interface_number, alternate_setting,
240 base::Bind(&HandlePassFailDeviceOperation,
241 base::Passed(&scoped_callbacks), kSetInterfaceFailed));
242 }
78 } 243 }
79 244
80 void WebUSBDeviceImpl::clearHalt( 245 void WebUSBDeviceImpl::clearHalt(
81 uint8_t endpoint_number, 246 uint8_t endpoint_number,
82 blink::WebUSBDeviceClearHaltCallbacks* callbacks) { 247 blink::WebUSBDeviceClearHaltCallbacks* callbacks) {
83 RejectAsNotImplemented(callbacks); 248 auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
249 if (!device_) {
250 RejectWithDeviceError(kDeviceNotOpened, scoped_callbacks.PassCallbacks());
251 } else {
252 device_->ClearHalt(
253 endpoint_number,
254 base::Bind(&HandlePassFailDeviceOperation,
255 base::Passed(&scoped_callbacks), kClearHaltFailed));
256 }
84 } 257 }
85 258
86 void WebUSBDeviceImpl::controlTransfer( 259 void WebUSBDeviceImpl::controlTransfer(
87 const blink::WebUSBDevice::ControlTransferParameters& parameters, 260 const blink::WebUSBDevice::ControlTransferParameters& parameters,
88 uint8_t* data, 261 uint8_t* data,
89 size_t data_size, 262 size_t data_size,
90 unsigned int timeout, 263 unsigned int timeout,
91 blink::WebUSBDeviceControlTransferCallbacks* callbacks) { 264 blink::WebUSBDeviceControlTransferCallbacks* callbacks) {
92 RejectAsNotImplemented(callbacks); 265 auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
266 if (!device_) {
267 RejectWithDeviceError(kDeviceNotOpened, scoped_callbacks.PassCallbacks());
268 } else {
269 device::usb::ControlTransferParamsPtr params =
270 device::usb::ControlTransferParams::From(parameters);
271 switch (parameters.direction) {
272 case WebUSBDevice::TransferDirection::In:
273 device_->ControlTransferIn(params.Pass(), data_size, timeout,
274 base::Bind(&OnTransferIn, base::Passed(&scoped_callbacks)));
275 break;
276 case WebUSBDevice::TransferDirection::Out: {
277 DCHECK(data);
278 std::vector<uint8_t> bytes(data, data + data_size);
279 mojo::Array<uint8_t> mojo_bytes;
280 mojo_bytes.Swap(&bytes);
281 device_->ControlTransferOut(params.Pass(), mojo_bytes.Pass(), timeout,
282 base::Bind(&OnTransferOut, base::Passed(&scoped_callbacks),
283 data_size));
284 break;
285 }
286 default:
287 NOTREACHED();
288 }
289 }
93 } 290 }
94 291
95 void WebUSBDeviceImpl::transfer( 292 void WebUSBDeviceImpl::transfer(
96 blink::WebUSBDevice::TransferDirection direction, 293 blink::WebUSBDevice::TransferDirection direction,
97 uint8_t endpoint_number, 294 uint8_t endpoint_number,
98 uint8_t* data, 295 uint8_t* data,
99 size_t data_size, 296 size_t data_size,
100 unsigned int timeout, 297 unsigned int timeout,
101 blink::WebUSBDeviceBulkTransferCallbacks* callbacks) { 298 blink::WebUSBDeviceBulkTransferCallbacks* callbacks) {
102 RejectAsNotImplemented(callbacks); 299 RejectWithDeviceError(kNotImplementedError, make_scoped_ptr(callbacks));
103 } 300 }
104 301
105 void WebUSBDeviceImpl::reset(blink::WebUSBDeviceResetCallbacks* callbacks) { 302 void WebUSBDeviceImpl::reset(blink::WebUSBDeviceResetCallbacks* callbacks) {
106 RejectAsNotImplemented(callbacks); 303 auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
304 if (!device_) {
305 RejectWithDeviceError(kDeviceNotOpened, scoped_callbacks.PassCallbacks());
306 } else {
307 device_->Reset(
308 base::Bind(&HandlePassFailDeviceOperation,
309 base::Passed(&scoped_callbacks), kDeviceResetFailed));
310 }
107 } 311 }
108 312
109 void WebUSBDeviceImpl::OnConnectionError() { 313 void WebUSBDeviceImpl::OnConnectionError() {
110 device_.reset(); 314 device_.reset();
111 } 315 }
112 316
113 } // namespace content 317 } // namespace content
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698