Commit d9ba49e1 authored by Reilly Grant's avatar Reilly Grant Committed by Commit Bot

[serial] Add monitor for device add/remove events on Windows

This change removes the old serial enumeration code on Windows and
always uses the new enumeration path while listening to window messages
to discover when ports are added and removed from the system.

This will allow us to keep the UI up-to-date in real time when the user
plugs in a device and deliver connection events to web apps.

Bug: 981483
Change-Id: I4126e370b02973458b5c2aac6a230244248b2320
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2099238
Commit-Queue: Reilly Grant <reillyg@chromium.org>
Reviewed-by: default avatarRobert Liao <robliao@chromium.org>
Cr-Commit-Position: refs/heads/master@{#751217}
parent 3f161ac2
...@@ -93,6 +93,7 @@ CHROME_DECLARE_HANDLE(HWND); ...@@ -93,6 +93,7 @@ CHROME_DECLARE_HANDLE(HWND);
typedef LPVOID HINTERNET; typedef LPVOID HINTERNET;
typedef HINSTANCE HMODULE; typedef HINSTANCE HMODULE;
typedef PVOID LSA_HANDLE; typedef PVOID LSA_HANDLE;
typedef PVOID HDEVINFO;
// Forward declare some Windows struct/typedef sets. // Forward declare some Windows struct/typedef sets.
...@@ -114,6 +115,8 @@ typedef struct tagMENUITEMINFOW MENUITEMINFOW, MENUITEMINFO; ...@@ -114,6 +115,8 @@ typedef struct tagMENUITEMINFOW MENUITEMINFOW, MENUITEMINFO;
typedef struct tagNMHDR NMHDR; typedef struct tagNMHDR NMHDR;
typedef struct _SP_DEVINFO_DATA SP_DEVINFO_DATA;
typedef PVOID PSID; typedef PVOID PSID;
// Declare Chrome versions of some Windows structures. These are needed for // Declare Chrome versions of some Windows structures. These are needed for
......
...@@ -7,9 +7,32 @@ ...@@ -7,9 +7,32 @@
#include <utility> #include <utility>
#include "base/unguessable_token.h" #include "base/unguessable_token.h"
#include "build/build_config.h"
#if defined(OS_LINUX)
#include "services/device/serial/serial_device_enumerator_linux.h"
#elif defined(OS_MACOSX)
#include "services/device/serial/serial_device_enumerator_mac.h"
#elif defined(OS_WIN)
#include "services/device/serial/serial_device_enumerator_win.h"
#endif
namespace device { namespace device {
// static
std::unique_ptr<SerialDeviceEnumerator> SerialDeviceEnumerator::Create(
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) {
#if defined(OS_LINUX)
return std::make_unique<SerialDeviceEnumeratorLinux>();
#elif defined(OS_MACOSX)
return std::make_unique<SerialDeviceEnumeratorMac>();
#elif defined(OS_WIN)
return std::make_unique<SerialDeviceEnumeratorWin>(std::move(ui_task_runner));
#else
#error "No implementation of SerialDeviceEnumerator on this platform."
#endif
}
SerialDeviceEnumerator::SerialDeviceEnumerator() = default; SerialDeviceEnumerator::SerialDeviceEnumerator() = default;
SerialDeviceEnumerator::~SerialDeviceEnumerator() = default; SerialDeviceEnumerator::~SerialDeviceEnumerator() = default;
......
...@@ -24,7 +24,8 @@ class SerialDeviceEnumerator { ...@@ -24,7 +24,8 @@ class SerialDeviceEnumerator {
public: public:
using TokenPathMap = std::map<base::UnguessableToken, base::FilePath>; using TokenPathMap = std::map<base::UnguessableToken, base::FilePath>;
static std::unique_ptr<SerialDeviceEnumerator> Create(); static std::unique_ptr<SerialDeviceEnumerator> Create(
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
SerialDeviceEnumerator(); SerialDeviceEnumerator();
virtual ~SerialDeviceEnumerator(); virtual ~SerialDeviceEnumerator();
......
...@@ -33,11 +33,6 @@ const char kRfcommMajor[] = "216"; ...@@ -33,11 +33,6 @@ const char kRfcommMajor[] = "216";
} // namespace } // namespace
// static
std::unique_ptr<SerialDeviceEnumerator> SerialDeviceEnumerator::Create() {
return std::make_unique<SerialDeviceEnumeratorLinux>();
}
SerialDeviceEnumeratorLinux::SerialDeviceEnumeratorLinux() { SerialDeviceEnumeratorLinux::SerialDeviceEnumeratorLinux() {
DETACH_FROM_SEQUENCE(sequence_checker_); DETACH_FROM_SEQUENCE(sequence_checker_);
......
...@@ -104,11 +104,6 @@ bool GetUInt16Property(io_service_t service, ...@@ -104,11 +104,6 @@ bool GetUInt16Property(io_service_t service,
} // namespace } // namespace
// static
std::unique_ptr<SerialDeviceEnumerator> SerialDeviceEnumerator::Create() {
return std::make_unique<SerialDeviceEnumeratorMac>();
}
SerialDeviceEnumeratorMac::SerialDeviceEnumeratorMac() { SerialDeviceEnumeratorMac::SerialDeviceEnumeratorMac() {
notify_port_.reset(IONotificationPortCreate(kIOMasterPortDefault)); notify_port_.reset(IONotificationPortCreate(kIOMasterPortDefault));
CFRunLoopAddSource(CFRunLoopGetMain(), CFRunLoopAddSource(CFRunLoopGetMain(),
......
...@@ -19,7 +19,7 @@ class SerialDeviceEnumeratorTest : public testing::Test { ...@@ -19,7 +19,7 @@ class SerialDeviceEnumeratorTest : public testing::Test {
: task_environment_(base::test::TaskEnvironment::MainThreadType::IO) {} : task_environment_(base::test::TaskEnvironment::MainThreadType::IO) {}
~SerialDeviceEnumeratorTest() override = default; ~SerialDeviceEnumeratorTest() override = default;
private: protected:
base::test::TaskEnvironment task_environment_; base::test::TaskEnvironment task_environment_;
}; };
...@@ -27,7 +27,8 @@ TEST_F(SerialDeviceEnumeratorTest, GetDevices) { ...@@ -27,7 +27,8 @@ TEST_F(SerialDeviceEnumeratorTest, GetDevices) {
// There is no guarantee that a test machine will have a serial device // There is no guarantee that a test machine will have a serial device
// available. The purpose of this test is to ensure that the process of // available. The purpose of this test is to ensure that the process of
// attempting to enumerate devices does not cause a crash. // attempting to enumerate devices does not cause a crash.
auto enumerator = SerialDeviceEnumerator::Create(); auto enumerator = SerialDeviceEnumerator::Create(
task_environment_.GetMainThreadTaskRunner());
ASSERT_TRUE(enumerator); ASSERT_TRUE(enumerator);
std::vector<mojom::SerialPortInfoPtr> devices = enumerator->GetDevices(); std::vector<mojom::SerialPortInfoPtr> devices = enumerator->GetDevices();
} }
......
...@@ -5,10 +5,10 @@ ...@@ -5,10 +5,10 @@
#ifndef SERVICES_DEVICE_SERIAL_SERIAL_DEVICE_ENUMERATOR_WIN_H_ #ifndef SERVICES_DEVICE_SERIAL_SERIAL_DEVICE_ENUMERATOR_WIN_H_
#define SERVICES_DEVICE_SERIAL_SERIAL_DEVICE_ENUMERATOR_WIN_H_ #define SERVICES_DEVICE_SERIAL_SERIAL_DEVICE_ENUMERATOR_WIN_H_
#include <vector>
#include "base/macros.h" #include "base/macros.h"
#include "base/optional.h" #include "base/scoped_observer.h"
#include "base/win/windows_types.h"
#include "device/base/device_monitor_win.h"
#include "services/device/serial/serial_device_enumerator.h" #include "services/device/serial/serial_device_enumerator.h"
namespace device { namespace device {
...@@ -16,21 +16,35 @@ namespace device { ...@@ -16,21 +16,35 @@ namespace device {
// Discovers and enumerates serial devices available to the host. // Discovers and enumerates serial devices available to the host.
class SerialDeviceEnumeratorWin : public SerialDeviceEnumerator { class SerialDeviceEnumeratorWin : public SerialDeviceEnumerator {
public: public:
SerialDeviceEnumeratorWin(); SerialDeviceEnumeratorWin(
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
~SerialDeviceEnumeratorWin() override; ~SerialDeviceEnumeratorWin() override;
// Implementation for SerialDeviceEnumerator.
std::vector<mojom::SerialPortInfoPtr> GetDevices() override;
// Searches for the COM port in the device's friendly name and returns the // Searches for the COM port in the device's friendly name and returns the
// appropriate device path or nullopt if the input did not contain a valid // appropriate device path or nullopt if the input did not contain a valid
// name. // name.
static base::Optional<base::FilePath> GetPath( static base::Optional<base::FilePath> GetPath(
const std::string& friendly_name); const std::string& friendly_name);
// SerialDeviceEnumerator
std::vector<mojom::SerialPortInfoPtr> GetDevices() override;
base::Optional<base::FilePath> GetPathFromToken(
const base::UnguessableToken& token) override;
void OnPathAdded(const base::string16& device_path);
void OnPathRemoved(const base::string16& device_path);
private: private:
std::vector<mojom::SerialPortInfoPtr> GetDevicesNew(); class UiThreadHelper;
std::vector<mojom::SerialPortInfoPtr> GetDevicesOld();
void DoInitialEnumeration();
void EnumeratePort(HDEVINFO dev_info, SP_DEVINFO_DATA* dev_info_data);
std::map<base::UnguessableToken, mojom::SerialPortInfoPtr> ports_;
std::map<base::FilePath, base::UnguessableToken> paths_;
std::unique_ptr<UiThreadHelper, base::OnTaskRunnerDeleter> helper_;
base::WeakPtrFactory<SerialDeviceEnumeratorWin> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(SerialDeviceEnumeratorWin); DISALLOW_COPY_AND_ASSIGN(SerialDeviceEnumeratorWin);
}; };
......
...@@ -36,7 +36,7 @@ void SerialPortManagerImpl::SetSerialEnumeratorForTesting( ...@@ -36,7 +36,7 @@ void SerialPortManagerImpl::SetSerialEnumeratorForTesting(
void SerialPortManagerImpl::GetDevices(GetDevicesCallback callback) { void SerialPortManagerImpl::GetDevices(GetDevicesCallback callback) {
if (!enumerator_) if (!enumerator_)
enumerator_ = SerialDeviceEnumerator::Create(); enumerator_ = SerialDeviceEnumerator::Create(ui_task_runner_);
std::move(callback).Run(enumerator_->GetDevices()); std::move(callback).Run(enumerator_->GetDevices());
} }
...@@ -45,7 +45,7 @@ void SerialPortManagerImpl::GetPort( ...@@ -45,7 +45,7 @@ void SerialPortManagerImpl::GetPort(
mojo::PendingReceiver<mojom::SerialPort> receiver, mojo::PendingReceiver<mojom::SerialPort> receiver,
mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher) { mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher) {
if (!enumerator_) if (!enumerator_)
enumerator_ = SerialDeviceEnumerator::Create(); enumerator_ = SerialDeviceEnumerator::Create(ui_task_runner_);
base::Optional<base::FilePath> path = enumerator_->GetPathFromToken(token); base::Optional<base::FilePath> path = enumerator_->GetPathFromToken(token);
if (path) { if (path) {
io_task_runner_->PostTask( io_task_runner_->PostTask(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment