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