blob: 4d93bcfd2d6b98ad8cb3725079a87f61bba6514f [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef EXTENSIONS_BROWSER_API_USB_USB_DEVICE_MANAGER_H_
#define EXTENSIONS_BROWSER_API_USB_USB_DEVICE_MANAGER_H_
#include <map>
#include <string>
#include <vector>
#include "base/containers/queue.h"
#include "base/memory/raw_ptr.h"
#include "base/observer_list.h"
#include "build/build_config.h"
#include "content/public/browser/browser_context.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
#include "extensions/browser/event_router.h"
#include "extensions/common/api/usb.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/device/public/mojom/usb_manager.mojom.h"
#include "services/device/public/mojom/usb_manager_client.mojom.h"
namespace extensions {
// A BrowserContext-scoped object which is registered as an observer of the
// EventRouter and UsbDeviceManager in order to manage the connection to the
// Device Service and generate device add/remove events.
class UsbDeviceManager : public BrowserContextKeyedAPI,
public EventRouter::Observer,
public device::mojom::UsbDeviceManagerClient {
public:
explicit UsbDeviceManager(content::BrowserContext* context);
~UsbDeviceManager() override;
UsbDeviceManager(const UsbDeviceManager&) = delete;
UsbDeviceManager& operator=(const UsbDeviceManager&) = delete;
static UsbDeviceManager* Get(content::BrowserContext* browser_context);
// BrowserContextKeyedAPI implementation.
static BrowserContextKeyedAPIFactory<UsbDeviceManager>* GetFactoryInstance();
class Observer : public base::CheckedObserver {
public:
virtual void OnDeviceAdded(const device::mojom::UsbDeviceInfo&);
virtual void OnDeviceRemoved(const device::mojom::UsbDeviceInfo&);
virtual void OnDeviceManagerConnectionError();
};
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
// Returns an ID for this device GUID. If the GUID is unknown to the
// UsbGuidMap a new ID is generated for it.
int GetIdFromGuid(const std::string& guid);
// Looks up a device GUID for a given extensions USB device ID. If the ID is
// unknown (e.g., the corresponding device was unplugged), this returns
// `false`; otherwise it returns `true`.
bool GetGuidFromId(int id, std::string* guid);
// Populates an instance of the chrome.usb.Device object from the given
// device.
void GetApiDevice(const device::mojom::UsbDeviceInfo& device_in,
api::usb::Device* device_out);
// Forward UsbDeviceManager methods.
void GetDevices(device::mojom::UsbDeviceManager::GetDevicesCallback callback);
void GetDevice(
const std::string& guid,
mojo::PendingReceiver<device::mojom::UsbDevice> device_receiver);
const device::mojom::UsbDeviceInfo* GetDeviceInfo(const std::string& guid);
bool UpdateActiveConfig(const std::string& guid, uint8_t config_value);
#if BUILDFLAG(IS_CHROMEOS)
void CheckAccess(
const std::string& guid,
device::mojom::UsbDeviceManager::CheckAccessCallback callback);
#endif // BUILDFLAG(IS_CHROMEOS)
void EnsureConnectionWithDeviceManager();
void SetDeviceManagerForTesting(
mojo::PendingRemote<device::mojom::UsbDeviceManager> fake_device_manager);
private:
friend class BrowserContextKeyedAPIFactory<UsbDeviceManager>;
// BrowserContextKeyedAPI implementation.
static const char* service_name() { return "UsbDeviceManager"; }
static const bool kServiceHasOwnInstanceInIncognito = true;
// KeyedService implementation.
void Shutdown() override;
// EventRouter::Observer implementation.
void OnListenerAdded(const EventListenerInfo& details) override;
// UsbService::Observer implementation.
void OnDeviceAdded(device::mojom::UsbDeviceInfoPtr device_info) override;
void OnDeviceRemoved(device::mojom::UsbDeviceInfoPtr device_info) override;
void SetUpDeviceManagerConnection();
void InitDeviceList(std::vector<device::mojom::UsbDeviceInfoPtr> devices);
void OnDeviceManagerConnectionError();
// Broadcasts a device add or remove event for the given device.
void DispatchEvent(const std::string& event_name,
const device::mojom::UsbDeviceInfo& device_info);
const raw_ptr<content::BrowserContext> browser_context_;
// Legacy integer IDs are used in USB extensions API so we need to maps USB
// device GUIDs to integer IDs.
int next_id_ = 0;
std::map<std::string, int> guid_to_id_map_;
std::map<int, std::string> id_to_guid_map_;
bool is_initialized_ = false;
base::queue<device::mojom::UsbDeviceManager::GetDevicesCallback>
pending_get_devices_requests_;
std::map<std::string, device::mojom::UsbDeviceInfoPtr> devices_;
// Connection to `device_manager_instance_`.
mojo::Remote<device::mojom::UsbDeviceManager> device_manager_;
mojo::AssociatedReceiver<device::mojom::UsbDeviceManagerClient>
client_receiver_{this};
base::ObserverList<Observer> observer_list_;
base::WeakPtrFactory<UsbDeviceManager> weak_factory_{this};
};
template <>
void BrowserContextKeyedAPIFactory<
UsbDeviceManager>::DeclareFactoryDependencies();
} // namespace extensions
#endif // EXTENSIONS_BROWSER_API_USB_USB_DEVICE_MANAGER_H_