1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef EXTENSIONS_BROWSER_API_HID_HID_DEVICE_MANAGER_H_ 6 #define EXTENSIONS_BROWSER_API_HID_HID_DEVICE_MANAGER_H_ 7 8 #include <map> 9 #include <memory> 10 #include <string> 11 #include <vector> 12 13 #include "base/callback.h" 14 #include "base/macros.h" 15 #include "base/memory/ref_counted.h" 16 #include "base/scoped_observer.h" 17 #include "base/threading/thread_checker.h" 18 #include "extensions/browser/browser_context_keyed_api_factory.h" 19 #include "extensions/browser/event_router.h" 20 #include "extensions/browser/extension_event_histogram_value.h" 21 #include "extensions/common/api/hid.h" 22 #include "mojo/public/cpp/bindings/associated_receiver.h" 23 #include "mojo/public/cpp/bindings/pending_remote.h" 24 #include "mojo/public/cpp/bindings/remote.h" 25 #include "services/device/public/mojom/hid.mojom.h" 26 27 namespace device { 28 class HidDeviceFilter; 29 } 30 31 namespace extensions { 32 33 class Extension; 34 35 // This class maps devices enumerated by device::HidManager to resource IDs 36 // returned by the chrome.hid API. 37 class HidDeviceManager : public BrowserContextKeyedAPI, 38 public device::mojom::HidManagerClient, 39 public EventRouter::Observer { 40 public: 41 typedef base::Callback<void(std::unique_ptr<base::ListValue>)> 42 GetApiDevicesCallback; 43 44 using ConnectCallback = device::mojom::HidManager::ConnectCallback; 45 46 explicit HidDeviceManager(content::BrowserContext* context); 47 ~HidDeviceManager() override; 48 49 // BrowserContextKeyedAPI implementation. 50 static BrowserContextKeyedAPIFactory<HidDeviceManager>* GetFactoryInstance(); 51 52 // Convenience method to get the HidDeviceManager for a profile. Get(content::BrowserContext * context)53 static HidDeviceManager* Get(content::BrowserContext* context) { 54 return BrowserContextKeyedAPIFactory<HidDeviceManager>::Get(context); 55 } 56 57 // Enumerates available devices, taking into account the permissions held by 58 // the given extension and the filters provided. The provided callback will 59 // be posted to the calling thread's task runner with a list of device info 60 // objects. 61 void GetApiDevices(const Extension* extension, 62 const std::vector<device::HidDeviceFilter>& filters, 63 const GetApiDevicesCallback& callback); 64 65 // Converts a list of device::mojom::HidDeviceInfo objects into a value that 66 // can be returned through the API. 67 std::unique_ptr<base::ListValue> GetApiDevicesFromList( 68 std::vector<device::mojom::HidDeviceInfoPtr> devices); 69 70 const device::mojom::HidDeviceInfo* GetDeviceInfo(int resource_id); 71 72 void Connect(const std::string& device_guid, ConnectCallback callback); 73 74 // Checks if |extension| has permission to open |device_info|. Set 75 // |update_last_used| to update the timestamp in the DevicePermissionsManager. 76 bool HasPermission(const Extension* extension, 77 const device::mojom::HidDeviceInfo& device_info, 78 bool update_last_used); 79 80 // Lazily perform an initial enumeration and set client to HidManager when 81 // the first API customer makes a request or registers an event listener. 82 virtual void LazyInitialize(); 83 84 // Allows tests to override where this class binds a HidManager receiver. 85 using HidManagerBinder = base::RepeatingCallback<void( 86 mojo::PendingReceiver<device::mojom::HidManager>)>; 87 static void OverrideHidManagerBinderForTesting(HidManagerBinder binder); 88 89 private: 90 friend class BrowserContextKeyedAPIFactory<HidDeviceManager>; 91 92 typedef std::map<int, device::mojom::HidDeviceInfoPtr> 93 ResourceIdToDeviceInfoMap; 94 typedef std::map<std::string, int> DeviceIdToResourceIdMap; 95 96 struct GetApiDevicesParams; 97 98 // KeyedService: 99 void Shutdown() override; 100 101 // BrowserContextKeyedAPI: service_name()102 static const char* service_name() { return "HidDeviceManager"; } 103 static const bool kServiceHasOwnInstanceInIncognito = true; 104 105 // EventRouter::Observer: 106 void OnListenerAdded(const EventListenerInfo& details) override; 107 108 // device::mojom::HidManagerClient implementation: 109 void DeviceAdded(device::mojom::HidDeviceInfoPtr device) override; 110 void DeviceRemoved(device::mojom::HidDeviceInfoPtr device) override; 111 112 // Builds a list of device info objects representing the currently enumerated 113 // devices, taking into account the permissions held by the given extension 114 // and the filters provided. 115 std::unique_ptr<base::ListValue> CreateApiDeviceList( 116 const Extension* extension, 117 const std::vector<device::HidDeviceFilter>& filters); 118 void OnEnumerationComplete( 119 std::vector<device::mojom::HidDeviceInfoPtr> devices); 120 121 void DispatchEvent(events::HistogramValue histogram_value, 122 const std::string& event_name, 123 std::unique_ptr<base::ListValue> event_args, 124 const device::mojom::HidDeviceInfo& device_info); 125 126 base::ThreadChecker thread_checker_; 127 content::BrowserContext* browser_context_ = nullptr; 128 EventRouter* event_router_ = nullptr; 129 bool initialized_ = false; 130 mojo::Remote<device::mojom::HidManager> hid_manager_; 131 mojo::AssociatedReceiver<device::mojom::HidManagerClient> receiver_{this}; 132 bool enumeration_ready_ = false; 133 std::vector<std::unique_ptr<GetApiDevicesParams>> pending_enumerations_; 134 int next_resource_id_ = 0; 135 ResourceIdToDeviceInfoMap devices_; 136 DeviceIdToResourceIdMap resource_ids_; 137 base::WeakPtrFactory<HidDeviceManager> weak_factory_{this}; 138 139 DISALLOW_COPY_AND_ASSIGN(HidDeviceManager); 140 }; 141 142 } // namespace extensions 143 144 #endif // EXTENSIONS_BROWSER_API_HID_HID_DEVICE_MANAGER_H_ 145