Chromium Code Reviews| 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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 46 if (mojoFilter->has_protocol_code) | 46 if (mojoFilter->has_protocol_code) |
| 47 mojoFilter->protocol_code = filter.protocolCode(); | 47 mojoFilter->protocol_code = filter.protocolCode(); |
| 48 if (filter.hasSerialNumber()) | 48 if (filter.hasSerialNumber()) |
| 49 mojoFilter->serial_number = filter.serialNumber(); | 49 mojoFilter->serial_number = filter.serialNumber(); |
| 50 return mojoFilter; | 50 return mojoFilter; |
| 51 } | 51 } |
| 52 | 52 |
| 53 } // namespace | 53 } // namespace |
| 54 | 54 |
| 55 USB::USB(LocalFrame& frame) | 55 USB::USB(LocalFrame& frame) |
| 56 : ContextLifecycleObserver(frame.document()), m_clientBinding(this) { | 56 : ContextLifecycleObserver(frame.document()), m_clientBinding(this) {} |
| 57 frame.interfaceProvider()->getInterface(mojo::MakeRequest(&m_deviceManager)); | |
| 58 m_deviceManager.set_connection_error_handler(convertToBaseCallback(WTF::bind( | |
| 59 &USB::onDeviceManagerConnectionError, wrapWeakPersistent(this)))); | |
| 60 m_deviceManager->SetClient(m_clientBinding.CreateInterfacePtrAndBind()); | |
| 61 } | |
| 62 | 57 |
| 63 USB::~USB() { | 58 USB::~USB() { |
| 64 // |m_deviceManager| and |m_chooserService| may still be valid but there | 59 // |m_deviceManager| and |m_chooserService| may still be valid but there |
| 65 // should be no more outstanding requests to them because each holds a | 60 // should be no more outstanding requests to them because each holds a |
| 66 // persistent handle to this object. | 61 // persistent handle to this object. |
| 67 DCHECK(m_deviceManagerRequests.isEmpty()); | 62 DCHECK(m_deviceManagerRequests.isEmpty()); |
| 68 DCHECK(m_chooserServiceRequests.isEmpty()); | 63 DCHECK(m_chooserServiceRequests.isEmpty()); |
| 69 } | 64 } |
| 70 | 65 |
| 71 void USB::dispose() { | 66 void USB::dispose() { |
| 72 // The pipe to this object must be closed when is marked unreachable to | 67 // The pipe to this object must be closed when is marked unreachable to |
| 73 // prevent messages from being dispatched before lazy sweeping. | 68 // prevent messages from being dispatched before lazy sweeping. |
| 74 m_clientBinding.Close(); | 69 m_clientBinding.Close(); |
| 75 } | 70 } |
| 76 | 71 |
| 77 ScriptPromise USB::getDevices(ScriptState* scriptState) { | 72 ScriptPromise USB::getDevices(ScriptState* scriptState) { |
| 78 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); | 73 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); |
| 79 ScriptPromise promise = resolver->promise(); | 74 ScriptPromise promise = resolver->promise(); |
| 75 ensureDeviceManagerConnection(); | |
| 80 if (!m_deviceManager) { | 76 if (!m_deviceManager) { |
| 81 resolver->reject(DOMException::create(NotSupportedError)); | 77 resolver->reject(DOMException::create(NotSupportedError)); |
| 82 } else { | 78 } else { |
| 83 m_deviceManagerRequests.insert(resolver); | 79 m_deviceManagerRequests.insert(resolver); |
| 84 m_deviceManager->GetDevices( | 80 m_deviceManager->GetDevices( |
| 85 nullptr, convertToBaseCallback(WTF::bind(&USB::onGetDevices, | 81 nullptr, convertToBaseCallback(WTF::bind(&USB::onGetDevices, |
| 86 wrapPersistent(this), | 82 wrapPersistent(this), |
| 87 wrapPersistent(resolver)))); | 83 wrapPersistent(resolver)))); |
| 88 } | 84 } |
| 89 return promise; | 85 return promise; |
| 90 } | 86 } |
| 91 | 87 |
| 92 ScriptPromise USB::requestDevice(ScriptState* scriptState, | 88 ScriptPromise USB::requestDevice(ScriptState* scriptState, |
| 93 const USBDeviceRequestOptions& options) { | 89 const USBDeviceRequestOptions& options) { |
| 94 ExecutionContext* executionContext = scriptState->getExecutionContext(); | |
| 95 | |
| 96 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); | 90 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); |
| 97 ScriptPromise promise = resolver->promise(); | 91 ScriptPromise promise = resolver->promise(); |
| 98 | 92 |
| 99 if (!m_chooserService) { | 93 if (!m_chooserService) { |
| 100 LocalFrame* frame = executionContext->isDocument() | 94 if (!frame()) { |
| 101 ? toDocument(executionContext)->frame() | |
| 102 : nullptr; | |
| 103 if (!frame) { | |
| 104 resolver->reject(DOMException::create(NotSupportedError)); | 95 resolver->reject(DOMException::create(NotSupportedError)); |
| 105 return promise; | 96 return promise; |
| 106 } | 97 } |
| 107 frame->interfaceProvider()->getInterface( | 98 frame()->interfaceProvider()->getInterface( |
| 108 mojo::MakeRequest(&m_chooserService)); | 99 mojo::MakeRequest(&m_chooserService)); |
| 109 m_chooserService.set_connection_error_handler( | 100 m_chooserService.set_connection_error_handler( |
| 110 convertToBaseCallback(WTF::bind(&USB::onChooserServiceConnectionError, | 101 convertToBaseCallback(WTF::bind(&USB::onChooserServiceConnectionError, |
| 111 wrapWeakPersistent(this)))); | 102 wrapWeakPersistent(this)))); |
| 112 } | 103 } |
| 113 | 104 |
| 114 if (!UserGestureIndicator::consumeUserGesture()) { | 105 if (!UserGestureIndicator::consumeUserGesture()) { |
| 115 resolver->reject(DOMException::create( | 106 resolver->reject(DOMException::create( |
| 116 SecurityError, | 107 SecurityError, |
| 117 "Must be handling a user gesture to show a permission request.")); | 108 "Must be handling a user gesture to show a permission request.")); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 173 m_deviceManagerRequests.erase(resolver); | 164 m_deviceManagerRequests.erase(resolver); |
| 174 } | 165 } |
| 175 | 166 |
| 176 void USB::onGetPermission(ScriptPromiseResolver* resolver, | 167 void USB::onGetPermission(ScriptPromiseResolver* resolver, |
| 177 usb::DeviceInfoPtr deviceInfo) { | 168 usb::DeviceInfoPtr deviceInfo) { |
| 178 auto requestEntry = m_chooserServiceRequests.find(resolver); | 169 auto requestEntry = m_chooserServiceRequests.find(resolver); |
| 179 if (requestEntry == m_chooserServiceRequests.end()) | 170 if (requestEntry == m_chooserServiceRequests.end()) |
| 180 return; | 171 return; |
| 181 m_chooserServiceRequests.erase(requestEntry); | 172 m_chooserServiceRequests.erase(requestEntry); |
| 182 | 173 |
| 174 ensureDeviceManagerConnection(); | |
| 183 if (!m_deviceManager) { | 175 if (!m_deviceManager) { |
| 184 resolver->reject(DOMException::create(NotFoundError, kNoServiceError)); | 176 resolver->reject(DOMException::create(NotFoundError, kNoServiceError)); |
| 185 return; | 177 return; |
| 186 } | 178 } |
| 187 | 179 |
| 188 if (deviceInfo) | 180 if (deviceInfo) { |
| 189 resolver->resolve(getOrCreateDevice(std::move(deviceInfo))); | 181 resolver->resolve(getOrCreateDevice(std::move(deviceInfo))); |
| 190 else | 182 } else { |
| 191 resolver->reject( | 183 resolver->reject( |
| 192 DOMException::create(NotFoundError, "No device selected.")); | 184 DOMException::create(NotFoundError, "No device selected.")); |
| 185 } | |
| 193 } | 186 } |
| 194 | 187 |
| 195 void USB::OnDeviceAdded(usb::DeviceInfoPtr deviceInfo) { | 188 void USB::OnDeviceAdded(usb::DeviceInfoPtr deviceInfo) { |
| 196 if (!m_deviceManager) | 189 if (!m_deviceManager) |
| 197 return; | 190 return; |
| 198 | 191 |
| 199 dispatchEvent(USBConnectionEvent::create( | 192 dispatchEvent(USBConnectionEvent::create( |
| 200 EventTypeNames::connect, getOrCreateDevice(std::move(deviceInfo)))); | 193 EventTypeNames::connect, getOrCreateDevice(std::move(deviceInfo)))); |
| 201 } | 194 } |
| 202 | 195 |
| 203 void USB::OnDeviceRemoved(usb::DeviceInfoPtr deviceInfo) { | 196 void USB::OnDeviceRemoved(usb::DeviceInfoPtr deviceInfo) { |
| 204 String guid = deviceInfo->guid; | 197 String guid = deviceInfo->guid; |
| 205 USBDevice* device = m_deviceCache.at(guid); | 198 USBDevice* device = m_deviceCache.at(guid); |
| 206 if (!device) | 199 if (!device) { |
| 207 device = USBDevice::create(std::move(deviceInfo), nullptr, | 200 device = USBDevice::create(std::move(deviceInfo), nullptr, |
| 208 getExecutionContext()); | 201 getExecutionContext()); |
| 202 } | |
| 209 dispatchEvent(USBConnectionEvent::create(EventTypeNames::disconnect, device)); | 203 dispatchEvent(USBConnectionEvent::create(EventTypeNames::disconnect, device)); |
| 210 m_deviceCache.erase(guid); | 204 m_deviceCache.erase(guid); |
| 211 } | 205 } |
| 212 | 206 |
| 213 void USB::onDeviceManagerConnectionError() { | 207 void USB::onDeviceManagerConnectionError() { |
| 214 m_deviceManager.reset(); | 208 m_deviceManager.reset(); |
| 209 m_clientBinding.Close(); | |
| 215 for (ScriptPromiseResolver* resolver : m_deviceManagerRequests) | 210 for (ScriptPromiseResolver* resolver : m_deviceManagerRequests) |
| 216 resolver->reject(DOMException::create(NotFoundError, kNoServiceError)); | 211 resolver->reject(DOMException::create(NotFoundError, kNoServiceError)); |
| 217 m_deviceManagerRequests.clear(); | 212 m_deviceManagerRequests.clear(); |
| 218 } | 213 } |
| 219 | 214 |
| 220 void USB::onChooserServiceConnectionError() { | 215 void USB::onChooserServiceConnectionError() { |
| 221 m_chooserService.reset(); | 216 m_chooserService.reset(); |
| 222 for (ScriptPromiseResolver* resolver : m_chooserServiceRequests) | 217 for (ScriptPromiseResolver* resolver : m_chooserServiceRequests) |
| 223 resolver->reject(DOMException::create(NotFoundError, kNoServiceError)); | 218 resolver->reject(DOMException::create(NotFoundError, kNoServiceError)); |
| 224 m_chooserServiceRequests.clear(); | 219 m_chooserServiceRequests.clear(); |
| 225 } | 220 } |
| 226 | 221 |
| 222 void USB::addedEventListener(const AtomicString& eventType, | |
| 223 RegisteredEventListener& listener) { | |
| 224 EventTargetWithInlineData::addedEventListener(eventType, listener); | |
| 225 if (eventType == EventTypeNames::connect || | |
| 226 eventType == EventTypeNames::disconnect) { | |
| 227 ensureDeviceManagerConnection(); | |
|
mcasas
2017/03/16 17:00:48
Can USB receive connect/disconnect events before
Reilly Grant (use Gerrit)
2017/03/16 17:43:14
Yes. An event will be dispatched whenever a device
| |
| 228 } | |
| 229 } | |
| 230 | |
| 231 void USB::ensureDeviceManagerConnection() { | |
| 232 if (m_deviceManager || !frame()) | |
| 233 return; | |
| 234 | |
| 235 frame()->interfaceProvider()->getInterface( | |
| 236 mojo::MakeRequest(&m_deviceManager)); | |
| 237 m_deviceManager.set_connection_error_handler(convertToBaseCallback(WTF::bind( | |
| 238 &USB::onDeviceManagerConnectionError, wrapWeakPersistent(this)))); | |
| 239 | |
| 240 DCHECK(!m_clientBinding.is_bound()); | |
| 241 m_deviceManager->SetClient(m_clientBinding.CreateInterfacePtrAndBind()); | |
| 242 } | |
| 243 | |
| 227 DEFINE_TRACE(USB) { | 244 DEFINE_TRACE(USB) { |
| 228 visitor->trace(m_deviceManagerRequests); | 245 visitor->trace(m_deviceManagerRequests); |
| 229 visitor->trace(m_chooserServiceRequests); | 246 visitor->trace(m_chooserServiceRequests); |
| 230 visitor->trace(m_deviceCache); | 247 visitor->trace(m_deviceCache); |
| 231 EventTargetWithInlineData::trace(visitor); | 248 EventTargetWithInlineData::trace(visitor); |
| 232 ContextLifecycleObserver::trace(visitor); | 249 ContextLifecycleObserver::trace(visitor); |
| 233 } | 250 } |
| 234 | 251 |
| 235 } // namespace blink | 252 } // namespace blink |
| OLD | NEW |