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

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: 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 3bd8b8fc2ed3e2bf0c951120c0da1548f8850d94..07e4a442343872abd708661387ca1da73e6a3861 100644
--- a/third_party/WebKit/Source/modules/webusb/USB.cpp
+++ b/third_party/WebKit/Source/modules/webusb/USB.cpp
@@ -4,7 +4,6 @@
#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"
@@ -12,117 +11,235 @@
#include "core/dom/ExceptionCode.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/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"
namespace blink {
namespace {
-void convertDeviceFilter(const USBDeviceFilter& filter, WebUSBDeviceFilter* webFilter)
+const char kNoServiceError[] = "USB service unavailable.";
+
+device::usb::blink::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 = device::usb::blink::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)
-{
- 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]);
+class DeviceChangeNotificationAdapter : public device::usb::blink::DeviceManager::GetDeviceChangesCallback::Runnable {
+ WTF_MAKE_NONCOPYABLE(DeviceChangeNotificationAdapter);
+
+public:
+ DeviceChangeNotificationAdapter(USB* usb) : m_usb(usb)
+ {
+ }
+
+ void Run(device::usb::blink::DeviceChangeNotificationPtr notification) const
+ {
+ if (m_usb)
+ m_usb->onDeviceChanges(std::move(notification));
}
-}
-// Allows using a CallbackPromiseAdapter with a WebVector to resolve the
-// getDevices() promise with a HeapVector owning USBDevices.
-class DeviceArray {
- STATIC_ONLY(DeviceArray);
+ device::usb::blink::DeviceManager::GetDeviceChangesCallback callback()
+ {
+ return device::usb::blink::DeviceManager::GetDeviceChangesCallback(this);
+ }
+
+private:
+ WeakPersistent<USB> m_usb;
+};
+
+template <typename Callback>
+class PromiseAdapterBase : public Callback::Runnable {
+ WTF_MAKE_NONCOPYABLE(PromiseAdapterBase);
+
public:
- using WebType = OwnPtr<WebVector<WebUSBDevice*>>;
+ PromiseAdapterBase(ScriptPromiseResolver* resolver) : m_resolver(resolver)
+ {
+ }
- static HeapVector<Member<USBDevice>> take(ScriptPromiseResolver* resolver, PassOwnPtr<WebVector<WebUSBDevice*>> webDevices)
+ ~PromiseAdapterBase() override
{
+ if (active())
+ m_resolver->reject(DOMException::create(NotFoundError, kNoServiceError));
+ }
+
+ template <typename T>
+ void resolve(T value) const
+ {
+ ASSERT(active());
+ m_resolver->resolve(value);
+ m_resolver = nullptr;
+ }
+
+ template <typename T>
+ void reject(T value) const
+ {
+ ASSERT(active());
+ m_resolver->reject(value);
+ m_resolver = nullptr;
+ }
+
+ bool active() const
+ {
+ return m_resolver && executionContext() && !executionContext()->activeDOMObjectsAreStopped();
+ }
+
+ Callback callback()
+ {
+ return Callback(this);
+ }
+
+ ExecutionContext* executionContext() const { return m_resolver->getExecutionContext(); }
+
+private:
+ // This field is mutable so that resolve() and reject() can be called from
+ // a mojo::Callback::Runnable's const Run() method.
esprehn 2016/04/06 20:10:45 this is really weird, callback interfaces generall
Reilly Grant (use Gerrit) 2016/04/06 22:30:07 mojo::Callback<>::Runnable::Run() is const because
esprehn 2016/04/06 22:42:38 Having to make your members mutable all over the c
+ mutable Persistent<ScriptPromiseResolver> m_resolver;
+};
+
+class GetDevicesPromiseAdapter : public PromiseAdapterBase<device::usb::blink::DeviceManager::GetDevicesCallback> {
+ WTF_MAKE_NONCOPYABLE(GetDevicesPromiseAdapter);
+
+public:
+ GetDevicesPromiseAdapter(USB* usb, ScriptPromiseResolver* resolver)
+ : PromiseAdapterBase(resolver)
+ , m_usb(usb)
+ {
+ }
+
+ void Run(mojo::WTFArray<device::usb::blink::DeviceInfoPtr> deviceInfos) const override
+ {
+ if (!active())
+ return;
+
HeapVector<Member<USBDevice>> devices;
- for (const auto webDevice : *webDevices)
- devices.append(USBDevice::create(adoptPtr(webDevice), resolver->getExecutionContext()));
- return devices;
+ for (size_t i = 0; i < deviceInfos.size(); ++i) {
esprehn 2016/04/06 20:10:45 range loop?
Reilly Grant (use Gerrit) 2016/04/06 22:30:07 Done.
+ device::usb::blink::DevicePtr device;
+ m_usb->deviceManager()->GetDevice(deviceInfos[i]->guid, mojo::GetProxy(&device));
+ devices.append(USBDevice::create(std::move(deviceInfos[i]), std::move(device), executionContext()));
+ }
+ resolve(devices);
+ }
+
+private:
+ Persistent<USB> m_usb;
+};
+
+class GetPermissionPromiseAdapter : public PromiseAdapterBase<device::usb::blink::ChooserService::GetPermissionCallback> {
+ WTF_MAKE_NONCOPYABLE(GetPermissionPromiseAdapter);
+
+public:
+ GetPermissionPromiseAdapter(USB* usb, ScriptPromiseResolver* resolver)
+ : PromiseAdapterBase(resolver)
+ , m_usb(usb)
+ {
+ }
+
+ void Run(device::usb::blink::DeviceInfoPtr deviceInfo) const override
+ {
+ if (!active())
+ return;
+
+ if (deviceInfo) {
+ device::usb::blink::DevicePtr device;
+ m_usb->deviceManager()->GetDevice(deviceInfo->guid, mojo::GetProxy(&device));
+ resolve(USBDevice::create(std::move(deviceInfo), std::move(device), executionContext()));
+ } else {
+ reject(DOMException::create(NotFoundError, "No device selected."));
+ }
}
+
+private:
+ Persistent<USB> m_usb;
};
} // namespace
USB::USB(LocalFrame& frame)
: ContextLifecycleObserver(frame.document())
- , m_client(USBController::from(frame).client())
{
- if (m_client)
- m_client->addObserver(this);
+ frame.serviceRegistry()->connectToRemoteService(mojo::GetProxy(&m_deviceManager));
+ m_deviceManager.set_connection_error_handler([this]() {
+ m_deviceManager.reset();
+ });
+ auto adapter = new DeviceChangeNotificationAdapter(this);
+ m_deviceManager->GetDeviceChanges(adapter->callback());
+ adapter = new DeviceChangeNotificationAdapter(this);
+ m_deviceManager->GetDeviceChanges(adapter->callback());
esprehn 2016/04/06 20:10:45 this seems to just do the exact same thing twice i
Reilly Grant (use Gerrit) 2016/04/06 22:30:07 Sorry, there was a comment why in the original cod
}
USB::~USB()
{
- if (m_client)
- m_client->removeObserver(this);
}
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 {
+ auto adapter = new GetDevicesPromiseAdapter(this, resolver);
+ m_deviceManager->GetDevices(nullptr, adapter->callback());
+ }
+ }
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() ? static_cast<Document*>(getExecutionContext())->frame() : nullptr;
esprehn 2016/04/06 20:10:45 toDocument() don't static_cast types in blink, our
Reilly Grant (use Gerrit) 2016/04/06 22:30:07 Done.
+ 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();
+ });
+ }
+ 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 {
+ mojo::WTFArray<device::usb::blink::DeviceFilterPtr> mojoFilters(options.hasFilters() ? options.filters().size() : 0);
+ if (options.hasFilters()) {
+ const auto& filters = options.filters();
+ for (size_t i = 0; i < filters.size(); ++i)
+ mojoFilters[i] = convertDeviceFilter(filters[i]);
+ }
+ auto adapter = new GetPermissionPromiseAdapter(this, resolver);
+ m_chooserService->GetPermission(std::move(mojoFilters), adapter->callback());
+ }
return promise;
}
@@ -138,19 +255,21 @@ const AtomicString& USB::interfaceName() const
void USB::contextDestroyed()
{
- if (m_client)
- m_client->removeObserver(this);
- m_client = nullptr;
+ m_deviceManager.reset();
+ m_chooserService.reset();
}
-void USB::onDeviceConnected(WebPassOwnPtr<WebUSBDevice> device)
+void USB::onDeviceChanges(device::usb::blink::DeviceChangeNotificationPtr notification)
{
- dispatchEvent(USBConnectionEvent::create(EventTypeNames::connect, USBDevice::create(device.release(), getExecutionContext())));
-}
-
-void USB::onDeviceDisconnected(WebPassOwnPtr<WebUSBDevice> device)
-{
- dispatchEvent(USBConnectionEvent::create(EventTypeNames::disconnect, USBDevice::create(device.release(), getExecutionContext())));
+ auto adapter = new DeviceChangeNotificationAdapter(this);
+ m_deviceManager->GetDeviceChanges(adapter->callback());
+ for (size_t i = 0; i < notification->devices_added.size(); ++i) {
+ device::usb::blink::DevicePtr device;
+ m_deviceManager->GetDevice(notification->devices_added[i]->guid, mojo::GetProxy(&device));
+ dispatchEvent(USBConnectionEvent::create(EventTypeNames::connect, USBDevice::create(std::move(notification->devices_added[i]), std::move(device), getExecutionContext())));
+ }
+ for (size_t i = 0; i < notification->devices_removed.size(); ++i)
+ dispatchEvent(USBConnectionEvent::create(EventTypeNames::disconnect, USBDevice::create(std::move(notification->devices_removed[i]), nullptr, getExecutionContext())));
}
DEFINE_TRACE(USB)

Powered by Google App Engine
This is Rietveld 408576698