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

Unified Diff: third_party/WebKit/Source/modules/webusb/USB.cpp

Issue 1850023002: Consume Mojo services directly in Blink's WebUSB implementation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Don't do assignments in if statements. Created 4 years, 8 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 side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/modules/webusb/USB.cpp
diff --git a/third_party/WebKit/Source/modules/webusb/USB.cpp b/third_party/WebKit/Source/modules/webusb/USB.cpp
index cd4b4aae2853894f8c7c83cbc119d74b7fdbb85d..4811ea22af4f0c53fa6bc874ea4271c4ea178d6c 100644
--- a/third_party/WebKit/Source/modules/webusb/USB.cpp
+++ b/third_party/WebKit/Source/modules/webusb/USB.cpp
@@ -4,133 +4,138 @@
#include "modules/webusb/USB.h"
-#include "bindings/core/v8/CallbackPromiseAdapter.h"
#include "bindings/core/v8/ScriptPromise.h"
#include "bindings/core/v8/ScriptPromiseResolver.h"
#include "core/dom/DOMException.h"
#include "core/dom/Document.h"
#include "core/dom/ExceptionCode.h"
+#include "device/usb/public/interfaces/device.mojom-wtf.h"
#include "modules/EventTargetModules.h"
#include "modules/webusb/USBConnectionEvent.h"
-#include "modules/webusb/USBController.h"
#include "modules/webusb/USBDevice.h"
#include "modules/webusb/USBDeviceFilter.h"
#include "modules/webusb/USBDeviceRequestOptions.h"
-#include "modules/webusb/USBError.h"
+#include "platform/MojoHelper.h"
#include "platform/UserGestureIndicator.h"
-#include "public/platform/Platform.h"
-#include "public/platform/WebVector.h"
-#include "public/platform/modules/webusb/WebUSBClient.h"
-#include "public/platform/modules/webusb/WebUSBDeviceFilter.h"
-#include "public/platform/modules/webusb/WebUSBDeviceRequestOptions.h"
-#include "public/platform/modules/webusb/WebUSBError.h"
+#include "public/platform/ServiceRegistry.h"
+#include "wtf/Functional.h"
+
+namespace usb = device::usb::wtf;
namespace blink {
namespace {
-void convertDeviceFilter(const USBDeviceFilter& filter, WebUSBDeviceFilter* webFilter)
+const char kNoServiceError[] = "USB service unavailable.";
+
+usb::DeviceFilterPtr convertDeviceFilter(const USBDeviceFilter& filter)
{
- webFilter->hasVendorID = filter.hasVendorId();
- if (filter.hasVendorId())
- webFilter->vendorID = filter.vendorId();
- webFilter->hasProductID = filter.hasProductId();
- if (filter.hasProductId())
- webFilter->productID = filter.productId();
- webFilter->hasClassCode = filter.hasClassCode();
- if (filter.hasClassCode())
- webFilter->classCode = filter.classCode();
- webFilter->hasSubclassCode = filter.hasSubclassCode();
- if (filter.hasSubclassCode())
- webFilter->subclassCode = filter.subclassCode();
- webFilter->hasProtocolCode = filter.hasProtocolCode();
- if (filter.hasProtocolCode())
- webFilter->protocolCode = filter.protocolCode();
+ auto mojoFilter = usb::DeviceFilter::New();
+ mojoFilter->has_vendor_id = filter.hasVendorId();
+ if (mojoFilter->has_vendor_id)
+ mojoFilter->vendor_id = filter.vendorId();
+ mojoFilter->has_product_id = filter.hasProductId();
+ if (mojoFilter->has_product_id)
+ mojoFilter->product_id = filter.productId();
+ mojoFilter->has_class_code = filter.hasClassCode();
+ if (mojoFilter->has_class_code)
+ mojoFilter->class_code = filter.classCode();
+ mojoFilter->has_subclass_code = filter.hasSubclassCode();
+ if (mojoFilter->has_subclass_code)
+ mojoFilter->subclass_code = filter.subclassCode();
+ mojoFilter->has_protocol_code = filter.hasProtocolCode();
+ if (mojoFilter->has_protocol_code)
+ mojoFilter->protocol_code = filter.protocolCode();
+ return mojoFilter;
}
-void convertDeviceRequestOptions(const USBDeviceRequestOptions& options, WebUSBDeviceRequestOptions* webOptions)
+bool isActive(ScriptPromiseResolver* resolver)
{
- DCHECK(options.hasFilters());
- webOptions->filters = WebVector<WebUSBDeviceFilter>(options.filters().size());
- for (size_t i = 0; i < options.filters().size(); ++i) {
- convertDeviceFilter(options.filters()[i], &webOptions->filters[i]);
- }
+ ExecutionContext* context = resolver->getExecutionContext();
+ return context && !context->activeDOMObjectsAreStopped();
}
-// Allows using a CallbackPromiseAdapter with a WebVector to resolve the
-// getDevices() promise with a HeapVector owning USBDevices.
-class DeviceArray {
- STATIC_ONLY(DeviceArray);
-public:
- using WebType = OwnPtr<WebVector<WebUSBDevice*>>;
-
- static HeapVector<Member<USBDevice>> take(ScriptPromiseResolver* resolver, PassOwnPtr<WebVector<WebUSBDevice*>> webDevices)
- {
- HeapVector<Member<USBDevice>> devices;
- for (const auto webDevice : *webDevices)
- devices.append(USBDevice::create(adoptPtr(webDevice), resolver->getExecutionContext()));
- return devices;
- }
-};
-
} // namespace
USB::USB(LocalFrame& frame)
: ContextLifecycleObserver(frame.document())
- , m_client(USBController::from(frame).client())
{
- ThreadState::current()->registerPreFinalizer(this);
- if (m_client)
- m_client->addObserver(this);
+ frame.serviceRegistry()->connectToRemoteService(mojo::GetProxy(&m_deviceManager));
+ m_deviceManager.set_connection_error_handler([this]() {
+ m_deviceManager.reset();
+ for (ScriptPromiseResolver* resolver : m_deviceManagerRequests) {
+ if (isActive(resolver))
+ resolver->reject(DOMException::create(NotFoundError, kNoServiceError));
+ }
+ m_deviceManagerRequests.clear();
+ });
+ // Set up two sequential calls to GetDeviceChanges to avoid latency.
+ m_deviceManager->GetDeviceChanges(createBaseCallback(bind<usb::DeviceChangeNotificationPtr>(&USB::onDeviceChanges, this)));
+ m_deviceManager->GetDeviceChanges(createBaseCallback(bind<usb::DeviceChangeNotificationPtr>(&USB::onDeviceChanges, this)));
}
USB::~USB()
{
-}
-
-void USB::dispose()
-{
- // Promptly clears a raw reference from content/ to an on-heap object
- // so that content/ doesn't access it in a lazy sweeping phase.
- if (m_client)
- m_client->removeObserver(this);
- m_client = nullptr;
+ DCHECK(!m_deviceManager);
+ DCHECK(m_deviceManagerRequests.isEmpty());
+ DCHECK(!m_chooserService);
+ DCHECK(m_chooserServiceRequests.isEmpty());
}
ScriptPromise USB::getDevices(ScriptState* scriptState)
{
- if (!m_client)
- return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(NotSupportedError));
-
- String errorMessage;
- if (!scriptState->getExecutionContext()->isSecureContext(errorMessage))
- return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(SecurityError, errorMessage));
-
ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
ScriptPromise promise = resolver->promise();
- m_client->getDevices(new CallbackPromiseAdapter<DeviceArray, USBError>(resolver));
-
+ if (!m_deviceManager) {
+ resolver->reject(DOMException::create(NotSupportedError));
+ } else {
+ String errorMessage;
+ if (!scriptState->getExecutionContext()->isSecureContext(errorMessage)) {
+ resolver->reject(DOMException::create(SecurityError, errorMessage));
+ } else {
+ m_deviceManagerRequests.add(resolver);
+ m_deviceManager->GetDevices(nullptr, createBaseCallback(bind<mojo::WTFArray<usb::DeviceInfoPtr>>(&USB::onGetDevices, this, resolver)));
+ }
+ }
return promise;
}
ScriptPromise USB::requestDevice(ScriptState* scriptState, const USBDeviceRequestOptions& options)
{
- if (!m_client)
- return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(NotSupportedError));
-
- String errorMessage;
- if (!scriptState->getExecutionContext()->isSecureContext(errorMessage))
- return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(SecurityError, errorMessage));
-
- if (!UserGestureIndicator::consumeUserGesture())
- return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(SecurityError, "Must be handling a user gesture to show a permission request."));
-
ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
ScriptPromise promise = resolver->promise();
- WebUSBDeviceRequestOptions webOptions;
- convertDeviceRequestOptions(options, &webOptions);
- m_client->requestDevice(webOptions, new CallbackPromiseAdapter<USBDevice, USBError>(resolver));
+ if (!m_chooserService) {
+ LocalFrame* frame = getExecutionContext() ? toDocument(getExecutionContext())->frame() : nullptr;
+ if (!frame) {
+ resolver->reject(DOMException::create(NotSupportedError));
+ return promise;
+ }
+ frame->serviceRegistry()->connectToRemoteService(mojo::GetProxy(&m_chooserService));
+ m_chooserService.set_connection_error_handler([this]() {
+ m_chooserService.reset();
+ for (ScriptPromiseResolver* resolver : m_chooserServiceRequests) {
+ if (isActive(resolver))
+ resolver->reject(DOMException::create(NotFoundError, kNoServiceError));
+ }
+ m_chooserServiceRequests.clear();
+ });
+ }
+ String errorMessage;
+ if (!scriptState->getExecutionContext()->isSecureContext(errorMessage)) {
+ resolver->reject(DOMException::create(SecurityError, errorMessage));
+ } else if (!UserGestureIndicator::consumeUserGesture()) {
+ resolver->reject(DOMException::create(SecurityError, "Must be handling a user gesture to show a permission request."));
+ } else {
+ Vector<usb::DeviceFilterPtr> filters;
+ if (options.hasFilters()) {
+ filters.reserveCapacity(options.filters().size());
+ for (const auto& filter : options.filters())
+ filters.append(convertDeviceFilter(filter));
+ }
+ m_chooserServiceRequests.add(resolver);
+ m_chooserService->GetPermission(std::move(filters), createBaseCallback(bind<usb::DeviceInfoPtr>(&USB::onGetPermission, this, resolver)));
+ }
return promise;
}
@@ -146,25 +151,59 @@ const AtomicString& USB::interfaceName() const
void USB::contextDestroyed()
{
- if (m_client)
- m_client->removeObserver(this);
- m_client = nullptr;
+ m_deviceManager.reset();
+ m_deviceManagerRequests.clear();
+ m_chooserService.reset();
+ m_chooserServiceRequests.clear();
}
-void USB::onDeviceConnected(std::unique_ptr<WebUSBDevice> device)
+void USB::onGetDevices(ScriptPromiseResolver* resolver, mojo::WTFArray<usb::DeviceInfoPtr> deviceInfos)
{
- dispatchEvent(USBConnectionEvent::create(EventTypeNames::connect, USBDevice::create(adoptPtr(device.release()), getExecutionContext())));
+ if (!isActive(resolver))
+ return;
+
+ HeapVector<Member<USBDevice>> devices;
+ for (auto& deviceInfo : deviceInfos.PassStorage()) {
+ usb::DevicePtr device;
+ m_deviceManager->GetDevice(deviceInfo->guid, mojo::GetProxy(&device));
+ devices.append(USBDevice::create(std::move(deviceInfo), std::move(device), resolver->getExecutionContext()));
+ }
+ resolver->resolve(devices);
+ m_deviceManagerRequests.remove(resolver);
+}
+
+void USB::onGetPermission(ScriptPromiseResolver* resolver, usb::DeviceInfoPtr deviceInfo)
+{
+ if (!isActive(resolver))
+ return;
+
+ if (deviceInfo) {
+ usb::DevicePtr device;
+ m_deviceManager->GetDevice(deviceInfo->guid, mojo::GetProxy(&device));
+ resolver->resolve(USBDevice::create(std::move(deviceInfo), std::move(device), resolver->getExecutionContext()));
+ } else {
+ resolver->reject(DOMException::create(NotFoundError, "No device selected."));
+ }
}
-void USB::onDeviceDisconnected(std::unique_ptr<WebUSBDevice> device)
+void USB::onDeviceChanges(usb::DeviceChangeNotificationPtr notification)
{
- dispatchEvent(USBConnectionEvent::create(EventTypeNames::disconnect, USBDevice::create(adoptPtr(device.release()), getExecutionContext())));
+ m_deviceManager->GetDeviceChanges(createBaseCallback(bind<usb::DeviceChangeNotificationPtr>(&USB::onDeviceChanges, this)));
+ for (auto& deviceInfo : notification->devices_added.PassStorage()) {
+ usb::DevicePtr device;
+ m_deviceManager->GetDevice(deviceInfo->guid, mojo::GetProxy(&device));
+ dispatchEvent(USBConnectionEvent::create(EventTypeNames::connect, USBDevice::create(std::move(deviceInfo), std::move(device), getExecutionContext())));
+ }
+ for (auto& deviceInfo : notification->devices_removed.PassStorage())
+ dispatchEvent(USBConnectionEvent::create(EventTypeNames::disconnect, USBDevice::create(std::move(deviceInfo), nullptr, getExecutionContext())));
}
DEFINE_TRACE(USB)
{
EventTargetWithInlineData::trace(visitor);
ContextLifecycleObserver::trace(visitor);
+ visitor->trace(m_deviceManagerRequests);
+ visitor->trace(m_chooserServiceRequests);
}
} // namespace blink
« no previous file with comments | « third_party/WebKit/Source/modules/webusb/USB.h ('k') | third_party/WebKit/Source/modules/webusb/USBAlternateInterface.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698