Skip to content

Commit

Permalink
Mojofication on //device/hid.
Browse files Browse the repository at this point in the history
In this CL:
1) Add the HidManager and HidConnection interfaces in hid.mojom, and
   implements those mojo interfaces in //device/hid.

2) Convert the clients in //extensions to use hid mojo interfaces.

3) Change the type of HidUsageAndPage::usage_page to uint16_t.

4) Rewrite the hid_apitest base on the new added mojo interfaces.

TODO:
1) Move client library files into device/hid/public/cpp.
2) Host HidService by DeviceService instead of DeviceClient.
3) Mojofy //device/u2f Or just move it into DeviceService.

BUG=728223

Change-Id: I1de1b5211f7ef37f54d4bc18c7995a3b47cc7da2
Reviewed-on: https://chromium-review.googlesource.com/648949
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Reilly Grant <reillyg@chromium.org>
Commit-Queue: Ke He <ke.he@intel.com>
Cr-Commit-Position: refs/heads/master@{#502109}
  • Loading branch information
Ke He authored and Commit Bot committed Sep 15, 2017
1 parent c359292 commit d2eea93
Show file tree
Hide file tree
Showing 27 changed files with 733 additions and 470 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
#include "chrome/test/base/testing_profile.h"
#include "device/base/mock_device_client.h"
#include "device/hid/hid_device_info.h"
#include "device/hid/mock_hid_service.h"
#include "device/hid/public/interfaces/hid.mojom.h"
#include "device/usb/mock_usb_device.h"
#include "device/usb/mock_usb_service.h"
Expand Down Expand Up @@ -40,9 +39,17 @@ const uint64_t kTestDeviceIds[] = {1, 2, 3, 4};
const char* kTestDeviceIds[] = {"A", "B", "C", "D"};
#endif

class FakeHidDeviceManager : public HidDeviceManager {
public:
explicit FakeHidDeviceManager(content::BrowserContext* context)
: HidDeviceManager(context) {}

void LazyInitialize() override {}
};

std::unique_ptr<KeyedService> CreateHidDeviceManager(
content::BrowserContext* context) {
return base::MakeUnique<HidDeviceManager>(context);
return base::MakeUnique<FakeHidDeviceManager>(context);
}

} // namespace
Expand Down Expand Up @@ -74,20 +81,15 @@ class DevicePermissionsManagerTest : public testing::Test {
device4_ = new HidDeviceInfo(
kTestDeviceIds[0], 0, 0, "Test HID Device", "abcde",
device::mojom::HidBusType::kHIDBusTypeUSB, std::vector<uint8_t>());
device_client_.hid_service()->AddDevice(device4_);
device5_ = new HidDeviceInfo(kTestDeviceIds[1], 0, 0, "Test HID Device", "",
device::mojom::HidBusType::kHIDBusTypeUSB,
std::vector<uint8_t>());
device_client_.hid_service()->AddDevice(device5_);
device6_ = new HidDeviceInfo(
kTestDeviceIds[2], 0, 0, "Test HID Device", "67890",
device::mojom::HidBusType::kHIDBusTypeUSB, std::vector<uint8_t>());
device_client_.hid_service()->AddDevice(device6_);
device7_ = new HidDeviceInfo(kTestDeviceIds[3], 0, 0, "Test HID Device", "",
device::mojom::HidBusType::kHIDBusTypeUSB,
std::vector<uint8_t>());
device_client_.hid_service()->AddDevice(device7_);
device_client_.hid_service()->FirstEnumerationComplete();
}

void TearDown() override { env_.reset(nullptr); }
Expand Down Expand Up @@ -209,11 +211,8 @@ TEST_F(DevicePermissionsManagerTest, DisconnectDevice) {
device_client_.usb_service()->RemoveDevice(device0_);
device_client_.usb_service()->RemoveDevice(device1_);

// Wait until HidDeviceManager::GetDevicesCallback is run. HidService
// won't send notifications to its observers before that.
base::RunLoop().RunUntilIdle();
device_client_.hid_service()->RemoveDevice(device4_->platform_device_id());
device_client_.hid_service()->RemoveDevice(device5_->platform_device_id());
manager->RemoveEntryByHidDeviceGUID(device4_->device_guid());
manager->RemoveEntryByHidDeviceGUID(device5_->device_guid());

// Device 0 will be accessible when it is reconnected because it can be
// recognized by its serial number.
Expand Down
1 change: 1 addition & 0 deletions content/public/app/mojo/content_browser_manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
"device": [
"device:battery_monitor",
"device:generic_sensor",
"device:hid",
"device:nfc",
"device:serial",
"device:vibration",
Expand Down
4 changes: 4 additions & 0 deletions device/hid/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ source_set("hid") {
"hid_collection_info.h",
"hid_connection.cc",
"hid_connection.h",
"hid_connection_impl.cc",
"hid_connection_impl.h",
"hid_connection_linux.cc",
"hid_connection_linux.h",
"hid_connection_mac.cc",
Expand All @@ -21,6 +23,8 @@ source_set("hid") {
"hid_device_filter.h",
"hid_device_info.cc",
"hid_device_info.h",
"hid_manager_impl.cc",
"hid_manager_impl.h",
"hid_report_descriptor.cc",
"hid_report_descriptor.h",
"hid_report_descriptor_item.cc",
Expand Down
113 changes: 113 additions & 0 deletions device/hid/hid_connection_impl.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "device/hid/hid_connection_impl.h"

#include "base/bind.h"
#include "base/memory/ptr_util.h"

namespace device {

HidConnectionImpl::HidConnectionImpl(
scoped_refptr<device::HidConnection> connection)
: hid_connection_(std::move(connection)), weak_factory_(this) {}

HidConnectionImpl::~HidConnectionImpl() {
DCHECK(hid_connection_);

// Close |hid_connection_| on destruction because this class is owned by a
// mojo::StrongBinding and will be destroyed when the pipe is closed.
hid_connection_->Close();
}

void HidConnectionImpl::Read(ReadCallback callback) {
DCHECK(hid_connection_);
hid_connection_->Read(base::BindOnce(&HidConnectionImpl::OnRead,
weak_factory_.GetWeakPtr(),
std::move(callback)));
}

void HidConnectionImpl::OnRead(ReadCallback callback,
bool success,
scoped_refptr<net::IOBuffer> buffer,
size_t size) {
if (!success) {
std::move(callback).Run(false, 0, base::nullopt);
return;
}
DCHECK(buffer);

std::vector<uint8_t> data(buffer->data() + 1, buffer->data() + size);
std::move(callback).Run(true, buffer->data()[0], data);
}

void HidConnectionImpl::Write(uint8_t report_id,
const std::vector<uint8_t>& buffer,
WriteCallback callback) {
DCHECK(hid_connection_);

auto io_buffer =
base::MakeRefCounted<net::IOBufferWithSize>(buffer.size() + 1);
io_buffer->data()[0] = report_id;

const char* data = reinterpret_cast<const char*>(buffer.data());
memcpy(io_buffer->data() + 1, data, buffer.size());

hid_connection_->Write(
io_buffer, io_buffer->size(),
base::BindOnce(&HidConnectionImpl::OnWrite, weak_factory_.GetWeakPtr(),
std::move(callback)));
}

void HidConnectionImpl::OnWrite(WriteCallback callback, bool success) {
std::move(callback).Run(success);
}

void HidConnectionImpl::GetFeatureReport(uint8_t report_id,
GetFeatureReportCallback callback) {
DCHECK(hid_connection_);
hid_connection_->GetFeatureReport(
report_id,
base::BindOnce(&HidConnectionImpl::OnGetFeatureReport,
weak_factory_.GetWeakPtr(), std::move(callback)));
}

void HidConnectionImpl::OnGetFeatureReport(GetFeatureReportCallback callback,
bool success,
scoped_refptr<net::IOBuffer> buffer,
size_t size) {
if (!success) {
std::move(callback).Run(false, base::nullopt);
return;
}
DCHECK(buffer);

std::vector<uint8_t> data(buffer->data(), buffer->data() + size);
std::move(callback).Run(true, data);
}

void HidConnectionImpl::SendFeatureReport(uint8_t report_id,
const std::vector<uint8_t>& buffer,
SendFeatureReportCallback callback) {
DCHECK(hid_connection_);

auto io_buffer =
base::MakeRefCounted<net::IOBufferWithSize>(buffer.size() + 1);
io_buffer->data()[0] = report_id;

const char* data = reinterpret_cast<const char*>(buffer.data());
memcpy(io_buffer->data() + 1, data, buffer.size());

hid_connection_->SendFeatureReport(
io_buffer, io_buffer->size(),
base::BindOnce(&HidConnectionImpl::OnSendFeatureReport,
weak_factory_.GetWeakPtr(), std::move(callback)));
}

void HidConnectionImpl::OnSendFeatureReport(SendFeatureReportCallback callback,
bool success) {
std::move(callback).Run(success);
}

} // namespace device
54 changes: 54 additions & 0 deletions device/hid/hid_connection_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef DEVICE_HID_HID_CONNECTION_IMPL_H_
#define DEVICE_HID_HID_CONNECTION_IMPL_H_

#include "base/memory/ref_counted.h"
#include "device/hid/hid_connection.h"
#include "device/hid/public/interfaces/hid.mojom.h"
#include "net/base/io_buffer.h"

namespace device {

// HidConnectionImpl is reponsible for handling mojo communications from
// clients. It delegates to HidConnection the real work of creating
// connections in different platforms.
class HidConnectionImpl : public device::mojom::HidConnection {
public:
explicit HidConnectionImpl(scoped_refptr<device::HidConnection> connection);
~HidConnectionImpl() final;

// device::mojom::HidConnection implementation:
void Read(ReadCallback callback) override;
void Write(uint8_t report_id,
const std::vector<uint8_t>& buffer,
WriteCallback callback) override;
void GetFeatureReport(uint8_t report_id,
GetFeatureReportCallback callback) override;
void SendFeatureReport(uint8_t report_id,
const std::vector<uint8_t>& buffer,
SendFeatureReportCallback callback) override;

private:
void OnRead(ReadCallback callback,
bool success,
scoped_refptr<net::IOBuffer> buffer,
size_t size);
void OnWrite(WriteCallback callback, bool success);
void OnGetFeatureReport(GetFeatureReportCallback callback,
bool success,
scoped_refptr<net::IOBuffer> buffer,
size_t size);
void OnSendFeatureReport(SendFeatureReportCallback callback, bool success);

scoped_refptr<device::HidConnection> hid_connection_;
base::WeakPtrFactory<HidConnectionImpl> weak_factory_;

DISALLOW_COPY_AND_ASSIGN(HidConnectionImpl);
};

} // namespace device

#endif // DEVICE_HID_HID_CONNECTION_IMPL_H_
101 changes: 101 additions & 0 deletions device/hid/hid_manager_impl.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "device/hid/hid_manager_impl.h"

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
#include "device/base/device_client.h"
#include "device/hid/hid_connection_impl.h"
#include "mojo/public/cpp/bindings/strong_binding.h"

namespace device {

HidManagerImpl::HidManagerImpl()
// TODO(ke.he@intel.com): Temporarily we still keep the HidService being
// owned and hosted in ChromeDeviceClient. The device service is shutdown
// earlier than ChromeDeviceClient, it is safe to hold a raw pointer of
// HidService here. After //device/u2f be mojofied or be moved into device
// service, we will remove HidService from the ChromeDeviceClient and let
// HidManagerImpl to own the HidService.
: hid_service_(DeviceClient::Get()->GetHidService()),
hid_service_observer_(this),
weak_factory_(this) {
DCHECK(hid_service_);
hid_service_observer_.Add(hid_service_);
}

HidManagerImpl::~HidManagerImpl() {}

void HidManagerImpl::AddBinding(device::mojom::HidManagerRequest request) {
bindings_.AddBinding(this, std::move(request));
}

void HidManagerImpl::GetDevicesAndSetClient(
device::mojom::HidManagerClientAssociatedPtrInfo client,
GetDevicesCallback callback) {
hid_service_->GetDevices(AdaptCallbackForRepeating(base::BindOnce(
&HidManagerImpl::CreateDeviceList, weak_factory_.GetWeakPtr(),
std::move(callback), std::move(client))));
}

void HidManagerImpl::GetDevices(GetDevicesCallback callback) {
hid_service_->GetDevices(AdaptCallbackForRepeating(base::BindOnce(
&HidManagerImpl::CreateDeviceList, weak_factory_.GetWeakPtr(),
std::move(callback), nullptr)));
}

void HidManagerImpl::CreateDeviceList(
GetDevicesCallback callback,
device::mojom::HidManagerClientAssociatedPtrInfo client,
std::vector<device::mojom::HidDeviceInfoPtr> devices) {
std::move(callback).Run(std::move(devices));

if (!client.is_valid())
return;

device::mojom::HidManagerClientAssociatedPtr client_ptr;
client_ptr.Bind(std::move(client));
clients_.AddPtr(std::move(client_ptr));
}

void HidManagerImpl::Connect(const std::string& device_guid,
ConnectCallback callback) {
hid_service_->Connect(device_guid,
AdaptCallbackForRepeating(base::BindOnce(
&HidManagerImpl::CreateConnection,
weak_factory_.GetWeakPtr(), std::move(callback))));
}

void HidManagerImpl::CreateConnection(
ConnectCallback callback,
scoped_refptr<device::HidConnection> connection) {
if (!connection) {
std::move(callback).Run(nullptr);
return;
}

device::mojom::HidConnectionPtr client;
mojo::MakeStrongBinding(base::MakeUnique<HidConnectionImpl>(connection),
mojo::MakeRequest(&client));
std::move(callback).Run(std::move(client));
}

void HidManagerImpl::OnDeviceAdded(device::mojom::HidDeviceInfoPtr device) {
device::mojom::HidDeviceInfo* device_info = device.get();
clients_.ForAllPtrs([device_info](device::mojom::HidManagerClient* client) {
client->DeviceAdded(device_info->Clone());
});
}

void HidManagerImpl::OnDeviceRemoved(device::mojom::HidDeviceInfoPtr device) {
device::mojom::HidDeviceInfo* device_info = device.get();
clients_.ForAllPtrs([device_info](device::mojom::HidManagerClient* client) {
client->DeviceRemoved(device_info->Clone());
});
}

} // namespace device
Loading

0 comments on commit d2eea93

Please sign in to comment.