| 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 |