OLD | NEW |
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 "modules/webusb/USB.h" | 5 #include "modules/webusb/USB.h" |
6 | 6 |
7 #include "bindings/core/v8/ScriptPromise.h" | 7 #include "bindings/core/v8/ScriptPromise.h" |
8 #include "bindings/core/v8/ScriptPromiseResolver.h" | 8 #include "bindings/core/v8/ScriptPromiseResolver.h" |
9 #include "core/dom/DOMException.h" | 9 #include "core/dom/DOMException.h" |
10 #include "core/dom/Document.h" | 10 #include "core/dom/Document.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 #include "public/platform/InterfaceProvider.h" | 21 #include "public/platform/InterfaceProvider.h" |
22 #include "public/platform/Platform.h" | 22 #include "public/platform/Platform.h" |
23 | 23 |
24 using device::mojom::blink::UsbDeviceFilterPtr; | 24 using device::mojom::blink::UsbDeviceFilterPtr; |
25 using device::mojom::blink::UsbDeviceInfoPtr; | 25 using device::mojom::blink::UsbDeviceInfoPtr; |
26 using device::mojom::blink::UsbDevicePtr; | 26 using device::mojom::blink::UsbDevicePtr; |
27 | 27 |
28 namespace blink { | 28 namespace blink { |
29 namespace { | 29 namespace { |
30 | 30 |
| 31 const char kFeaturePolicyBlocked[] = |
| 32 "Access to the feature \"usb\" is disallowed by feature policy."; |
| 33 const char kIframeBlocked[] = |
| 34 "Access to this method is not allowed in embedded frames."; |
31 const char kNoDeviceSelected[] = "No device selected."; | 35 const char kNoDeviceSelected[] = "No device selected."; |
32 | 36 |
33 UsbDeviceFilterPtr ConvertDeviceFilter(const USBDeviceFilter& filter) { | 37 UsbDeviceFilterPtr ConvertDeviceFilter(const USBDeviceFilter& filter) { |
34 auto mojo_filter = device::mojom::blink::UsbDeviceFilter::New(); | 38 auto mojo_filter = device::mojom::blink::UsbDeviceFilter::New(); |
35 mojo_filter->has_vendor_id = filter.hasVendorId(); | 39 mojo_filter->has_vendor_id = filter.hasVendorId(); |
36 if (mojo_filter->has_vendor_id) | 40 if (mojo_filter->has_vendor_id) |
37 mojo_filter->vendor_id = filter.vendorId(); | 41 mojo_filter->vendor_id = filter.vendorId(); |
38 mojo_filter->has_product_id = filter.hasProductId(); | 42 mojo_filter->has_product_id = filter.hasProductId(); |
39 if (mojo_filter->has_product_id) | 43 if (mojo_filter->has_product_id) |
40 mojo_filter->product_id = filter.productId(); | 44 mojo_filter->product_id = filter.productId(); |
(...skipping 24 matching lines...) Expand all Loading... |
65 DCHECK(chooser_service_requests_.IsEmpty()); | 69 DCHECK(chooser_service_requests_.IsEmpty()); |
66 } | 70 } |
67 | 71 |
68 void USB::Dispose() { | 72 void USB::Dispose() { |
69 // The pipe to this object must be closed when is marked unreachable to | 73 // The pipe to this object must be closed when is marked unreachable to |
70 // prevent messages from being dispatched before lazy sweeping. | 74 // prevent messages from being dispatched before lazy sweeping. |
71 client_binding_.Close(); | 75 client_binding_.Close(); |
72 } | 76 } |
73 | 77 |
74 ScriptPromise USB::getDevices(ScriptState* script_state) { | 78 ScriptPromise USB::getDevices(ScriptState* script_state) { |
| 79 LocalFrame* frame = GetFrame(); |
| 80 if (!frame) { |
| 81 return ScriptPromise::RejectWithDOMException( |
| 82 script_state, DOMException::Create(kNotSupportedError)); |
| 83 } |
| 84 |
| 85 if (RuntimeEnabledFeatures::featurePolicyEnabled()) { |
| 86 if (!frame->IsFeatureEnabled(WebFeaturePolicyFeature::kUsb)) { |
| 87 return ScriptPromise::RejectWithDOMException( |
| 88 script_state, |
| 89 DOMException::Create(kSecurityError, kFeaturePolicyBlocked)); |
| 90 } |
| 91 } else if (!frame->IsMainFrame()) { |
| 92 return ScriptPromise::RejectWithDOMException( |
| 93 script_state, DOMException::Create(kSecurityError, kIframeBlocked)); |
| 94 } |
| 95 |
| 96 EnsureDeviceManagerConnection(); |
75 ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); | 97 ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); |
76 ScriptPromise promise = resolver->Promise(); | 98 device_manager_requests_.insert(resolver); |
77 EnsureDeviceManagerConnection(); | 99 device_manager_->GetDevices( |
78 if (!device_manager_) { | 100 nullptr, |
79 resolver->Reject(DOMException::Create(kNotSupportedError)); | 101 ConvertToBaseCallback(WTF::Bind(&USB::OnGetDevices, WrapPersistent(this), |
80 } else { | 102 WrapPersistent(resolver)))); |
81 device_manager_requests_.insert(resolver); | 103 return resolver->Promise(); |
82 device_manager_->GetDevices( | |
83 nullptr, ConvertToBaseCallback(WTF::Bind(&USB::OnGetDevices, | |
84 WrapPersistent(this), | |
85 WrapPersistent(resolver)))); | |
86 } | |
87 return promise; | |
88 } | 104 } |
89 | 105 |
90 ScriptPromise USB::requestDevice(ScriptState* script_state, | 106 ScriptPromise USB::requestDevice(ScriptState* script_state, |
91 const USBDeviceRequestOptions& options) { | 107 const USBDeviceRequestOptions& options) { |
92 ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); | 108 LocalFrame* frame = GetFrame(); |
93 ScriptPromise promise = resolver->Promise(); | 109 if (!frame) { |
| 110 return ScriptPromise::RejectWithDOMException( |
| 111 script_state, DOMException::Create(kNotSupportedError)); |
| 112 } |
| 113 |
| 114 if (RuntimeEnabledFeatures::featurePolicyEnabled()) { |
| 115 if (!frame->IsFeatureEnabled(WebFeaturePolicyFeature::kUsb)) { |
| 116 return ScriptPromise::RejectWithDOMException( |
| 117 script_state, |
| 118 DOMException::Create(kSecurityError, kFeaturePolicyBlocked)); |
| 119 } |
| 120 } else if (!frame->IsMainFrame()) { |
| 121 return ScriptPromise::RejectWithDOMException( |
| 122 script_state, DOMException::Create(kSecurityError, kIframeBlocked)); |
| 123 } |
94 | 124 |
95 if (!chooser_service_) { | 125 if (!chooser_service_) { |
96 if (!GetFrame()) { | |
97 resolver->Reject(DOMException::Create(kNotSupportedError)); | |
98 return promise; | |
99 } | |
100 GetFrame()->GetInterfaceProvider()->GetInterface( | 126 GetFrame()->GetInterfaceProvider()->GetInterface( |
101 mojo::MakeRequest(&chooser_service_)); | 127 mojo::MakeRequest(&chooser_service_)); |
102 chooser_service_.set_connection_error_handler( | 128 chooser_service_.set_connection_error_handler( |
103 ConvertToBaseCallback(WTF::Bind(&USB::OnChooserServiceConnectionError, | 129 ConvertToBaseCallback(WTF::Bind(&USB::OnChooserServiceConnectionError, |
104 WrapWeakPersistent(this)))); | 130 WrapWeakPersistent(this)))); |
105 } | 131 } |
106 | 132 |
107 if (!UserGestureIndicator::ConsumeUserGesture()) { | 133 if (!UserGestureIndicator::ConsumeUserGesture()) { |
108 resolver->Reject(DOMException::Create( | 134 return ScriptPromise::RejectWithDOMException( |
109 kSecurityError, | 135 script_state, |
110 "Must be handling a user gesture to show a permission request.")); | 136 DOMException::Create( |
111 } else { | 137 kSecurityError, |
112 Vector<UsbDeviceFilterPtr> filters; | 138 "Must be handling a user gesture to show a permission request.")); |
113 if (options.hasFilters()) { | |
114 filters.ReserveCapacity(options.filters().size()); | |
115 for (const auto& filter : options.filters()) | |
116 filters.push_back(ConvertDeviceFilter(filter)); | |
117 } | |
118 chooser_service_requests_.insert(resolver); | |
119 chooser_service_->GetPermission( | |
120 std::move(filters), ConvertToBaseCallback(WTF::Bind( | |
121 &USB::OnGetPermission, WrapPersistent(this), | |
122 WrapPersistent(resolver)))); | |
123 } | 139 } |
124 return promise; | 140 |
| 141 Vector<UsbDeviceFilterPtr> filters; |
| 142 if (options.hasFilters()) { |
| 143 filters.ReserveCapacity(options.filters().size()); |
| 144 for (const auto& filter : options.filters()) |
| 145 filters.push_back(ConvertDeviceFilter(filter)); |
| 146 } |
| 147 |
| 148 ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); |
| 149 chooser_service_requests_.insert(resolver); |
| 150 chooser_service_->GetPermission( |
| 151 std::move(filters), ConvertToBaseCallback(WTF::Bind( |
| 152 &USB::OnGetPermission, WrapPersistent(this), |
| 153 WrapPersistent(resolver)))); |
| 154 return resolver->Promise(); |
125 } | 155 } |
126 | 156 |
127 ExecutionContext* USB::GetExecutionContext() const { | 157 ExecutionContext* USB::GetExecutionContext() const { |
128 return ContextLifecycleObserver::GetExecutionContext(); | 158 return ContextLifecycleObserver::GetExecutionContext(); |
129 } | 159 } |
130 | 160 |
131 const AtomicString& USB::InterfaceName() const { | 161 const AtomicString& USB::InterfaceName() const { |
132 return EventTargetNames::USB; | 162 return EventTargetNames::USB; |
133 } | 163 } |
134 | 164 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 | 198 |
169 void USB::OnGetPermission(ScriptPromiseResolver* resolver, | 199 void USB::OnGetPermission(ScriptPromiseResolver* resolver, |
170 UsbDeviceInfoPtr device_info) { | 200 UsbDeviceInfoPtr device_info) { |
171 auto request_entry = chooser_service_requests_.find(resolver); | 201 auto request_entry = chooser_service_requests_.find(resolver); |
172 if (request_entry == chooser_service_requests_.end()) | 202 if (request_entry == chooser_service_requests_.end()) |
173 return; | 203 return; |
174 chooser_service_requests_.erase(request_entry); | 204 chooser_service_requests_.erase(request_entry); |
175 | 205 |
176 EnsureDeviceManagerConnection(); | 206 EnsureDeviceManagerConnection(); |
177 | 207 |
178 if (device_manager_ && device_info) { | 208 if (device_manager_ && device_info) |
179 resolver->Resolve(GetOrCreateDevice(std::move(device_info))); | 209 resolver->Resolve(GetOrCreateDevice(std::move(device_info))); |
180 } else { | 210 else |
181 resolver->Reject(DOMException::Create(kNotFoundError, kNoDeviceSelected)); | 211 resolver->Reject(DOMException::Create(kNotFoundError, kNoDeviceSelected)); |
182 } | |
183 } | 212 } |
184 | 213 |
185 void USB::OnDeviceAdded(UsbDeviceInfoPtr device_info) { | 214 void USB::OnDeviceAdded(UsbDeviceInfoPtr device_info) { |
186 if (!device_manager_) | 215 if (!device_manager_) |
187 return; | 216 return; |
188 | 217 |
189 DispatchEvent(USBConnectionEvent::Create( | 218 DispatchEvent(USBConnectionEvent::Create( |
190 EventTypeNames::connect, GetOrCreateDevice(std::move(device_info)))); | 219 EventTypeNames::connect, GetOrCreateDevice(std::move(device_info)))); |
191 } | 220 } |
192 | 221 |
(...skipping 19 matching lines...) Expand all Loading... |
212 void USB::OnChooserServiceConnectionError() { | 241 void USB::OnChooserServiceConnectionError() { |
213 chooser_service_.reset(); | 242 chooser_service_.reset(); |
214 for (ScriptPromiseResolver* resolver : chooser_service_requests_) | 243 for (ScriptPromiseResolver* resolver : chooser_service_requests_) |
215 resolver->Reject(DOMException::Create(kNotFoundError, kNoDeviceSelected)); | 244 resolver->Reject(DOMException::Create(kNotFoundError, kNoDeviceSelected)); |
216 chooser_service_requests_.clear(); | 245 chooser_service_requests_.clear(); |
217 } | 246 } |
218 | 247 |
219 void USB::AddedEventListener(const AtomicString& event_type, | 248 void USB::AddedEventListener(const AtomicString& event_type, |
220 RegisteredEventListener& listener) { | 249 RegisteredEventListener& listener) { |
221 EventTargetWithInlineData::AddedEventListener(event_type, listener); | 250 EventTargetWithInlineData::AddedEventListener(event_type, listener); |
222 if (event_type == EventTypeNames::connect || | 251 if (event_type != EventTypeNames::connect && |
223 event_type == EventTypeNames::disconnect) { | 252 event_type != EventTypeNames::disconnect) { |
| 253 return; |
| 254 } |
| 255 |
| 256 LocalFrame* frame = GetFrame(); |
| 257 if (!frame) |
| 258 return; |
| 259 |
| 260 if (RuntimeEnabledFeatures::featurePolicyEnabled()) { |
| 261 if (frame->IsFeatureEnabled(WebFeaturePolicyFeature::kUsb)) |
| 262 EnsureDeviceManagerConnection(); |
| 263 } else if (frame->IsMainFrame()) { |
224 EnsureDeviceManagerConnection(); | 264 EnsureDeviceManagerConnection(); |
225 } | 265 } |
226 } | 266 } |
227 | 267 |
228 void USB::EnsureDeviceManagerConnection() { | 268 void USB::EnsureDeviceManagerConnection() { |
229 if (device_manager_ || !GetFrame()) | 269 if (device_manager_) |
230 return; | 270 return; |
231 | 271 |
| 272 DCHECK(GetFrame()); |
232 GetFrame()->GetInterfaceProvider()->GetInterface( | 273 GetFrame()->GetInterfaceProvider()->GetInterface( |
233 mojo::MakeRequest(&device_manager_)); | 274 mojo::MakeRequest(&device_manager_)); |
234 device_manager_.set_connection_error_handler(ConvertToBaseCallback(WTF::Bind( | 275 device_manager_.set_connection_error_handler(ConvertToBaseCallback(WTF::Bind( |
235 &USB::OnDeviceManagerConnectionError, WrapWeakPersistent(this)))); | 276 &USB::OnDeviceManagerConnectionError, WrapWeakPersistent(this)))); |
236 | 277 |
237 DCHECK(!client_binding_.is_bound()); | 278 DCHECK(!client_binding_.is_bound()); |
238 device_manager_->SetClient(client_binding_.CreateInterfacePtrAndBind()); | 279 device_manager_->SetClient(client_binding_.CreateInterfacePtrAndBind()); |
239 } | 280 } |
240 | 281 |
241 DEFINE_TRACE(USB) { | 282 DEFINE_TRACE(USB) { |
242 visitor->Trace(device_manager_requests_); | 283 visitor->Trace(device_manager_requests_); |
243 visitor->Trace(chooser_service_requests_); | 284 visitor->Trace(chooser_service_requests_); |
244 visitor->Trace(device_cache_); | 285 visitor->Trace(device_cache_); |
245 EventTargetWithInlineData::Trace(visitor); | 286 EventTargetWithInlineData::Trace(visitor); |
246 ContextLifecycleObserver::Trace(visitor); | 287 ContextLifecycleObserver::Trace(visitor); |
247 } | 288 } |
248 | 289 |
249 } // namespace blink | 290 } // namespace blink |
OLD | NEW |