1 // Copyright 2019 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 CHROME_BROWSER_HID_HID_CHOOSER_CONTEXT_H_ 6 #define CHROME_BROWSER_HID_HID_CHOOSER_CONTEXT_H_ 7 8 #include <map> 9 #include <memory> 10 #include <set> 11 #include <string> 12 #include <utility> 13 #include <vector> 14 15 #include "base/memory/weak_ptr.h" 16 #include "base/observer_list.h" 17 #include "base/unguessable_token.h" 18 #include "components/permissions/chooser_context_base.h" 19 #include "mojo/public/cpp/bindings/associated_receiver.h" 20 #include "mojo/public/cpp/bindings/pending_remote.h" 21 #include "mojo/public/cpp/bindings/remote.h" 22 #include "services/device/public/mojom/hid.mojom.h" 23 #include "url/origin.h" 24 25 class Profile; 26 27 namespace base { 28 class Value; 29 } 30 31 // Manages the internal state and connection to the device service for the 32 // Human Interface Device (HID) chooser UI. 33 class HidChooserContext : public permissions::ChooserContextBase, 34 public device::mojom::HidManagerClient { 35 public: 36 // This observer can be used to be notified when HID devices are connected or 37 // disconnected. 38 class DeviceObserver : public base::CheckedObserver { 39 public: 40 virtual void OnDeviceAdded(const device::mojom::HidDeviceInfo&); 41 virtual void OnDeviceRemoved(const device::mojom::HidDeviceInfo&); 42 virtual void OnHidManagerConnectionError(); 43 44 // Called when the HidChooserContext is shutting down. Observers must remove 45 // themselves before returning. 46 virtual void OnHidChooserContextShutdown() = 0; 47 }; 48 49 explicit HidChooserContext(Profile* profile); 50 HidChooserContext(const HidChooserContext&) = delete; 51 HidChooserContext& operator=(const HidChooserContext&) = delete; 52 ~HidChooserContext() override; 53 54 // Returns a human-readable string identifier for |device|. 55 static base::string16 DisplayNameFromDeviceInfo( 56 const device::mojom::HidDeviceInfo& device); 57 58 // permissions::ChooserContextBase implementation: 59 bool IsValidObject(const base::Value& object) override; 60 // In addition these methods from ChooserContextBase are overridden in order 61 // to expose ephemeral devices through the public interface. 62 std::vector<std::unique_ptr<Object>> GetGrantedObjects( 63 const url::Origin& requesting_origin, 64 const url::Origin& embedding_origin) override; 65 std::vector<std::unique_ptr<Object>> GetAllGrantedObjects() override; 66 void RevokeObjectPermission(const url::Origin& requesting_origin, 67 const url::Origin& embedding_origin, 68 const base::Value& object) override; 69 base::string16 GetObjectDisplayName(const base::Value& object) override; 70 71 // HID-specific interface for granting and checking permissions. 72 void GrantDevicePermission(const url::Origin& requesting_origin, 73 const url::Origin& embedding_origin, 74 const device::mojom::HidDeviceInfo& device); 75 bool HasDevicePermission(const url::Origin& requesting_origin, 76 const url::Origin& embedding_origin, 77 const device::mojom::HidDeviceInfo& device); 78 79 // For ScopedObserver. 80 void AddDeviceObserver(DeviceObserver* observer); 81 void RemoveDeviceObserver(DeviceObserver* observer); 82 83 // Forward HidManager::GetDevices. 84 void GetDevices(device::mojom::HidManager::GetDevicesCallback callback); 85 86 // Only call this if you're sure |devices_| has been initialized before-hand. 87 // The returned raw pointer is owned by |devices_| and will be destroyed when 88 // the device is removed. 89 const device::mojom::HidDeviceInfo* GetDeviceInfo(const std::string& guid); 90 91 device::mojom::HidManager* GetHidManager(); 92 93 // Sets |manager| as the HidManager and registers this context as a 94 // HidManagerClient. Calls |callback| with the set of enumerated devices once 95 // the client is registered and the initial enumeration is complete. 96 void SetHidManagerForTesting( 97 mojo::PendingRemote<device::mojom::HidManager> manager, 98 device::mojom::HidManager::GetDevicesCallback callback); 99 100 base::WeakPtr<HidChooserContext> AsWeakPtr(); 101 102 private: 103 // device::mojom::HidManagerClient implementation: 104 void DeviceAdded(device::mojom::HidDeviceInfoPtr device_info) override; 105 void DeviceRemoved(device::mojom::HidDeviceInfoPtr device_info) override; 106 107 void EnsureHidManagerConnection(); 108 void SetUpHidManagerConnection( 109 mojo::PendingRemote<device::mojom::HidManager> manager); 110 void InitDeviceList(std::vector<device::mojom::HidDeviceInfoPtr> devices); 111 void OnHidManagerConnectionError(); 112 113 const bool is_incognito_; 114 bool is_initialized_ = false; 115 base::queue<device::mojom::HidManager::GetDevicesCallback> 116 pending_get_devices_requests_; 117 118 // Tracks the set of devices to which an origin (potentially embedded in 119 // another origin) has access to. Key is (requesting_origin, 120 // embedding_origin). 121 std::map<std::pair<url::Origin, url::Origin>, std::set<std::string>> 122 ephemeral_devices_; 123 124 // Map from device GUID to device info. 125 std::map<std::string, device::mojom::HidDeviceInfoPtr> devices_; 126 127 mojo::Remote<device::mojom::HidManager> hid_manager_; 128 mojo::AssociatedReceiver<device::mojom::HidManagerClient> client_receiver_{ 129 this}; 130 base::ObserverList<DeviceObserver> device_observer_list_; 131 132 base::WeakPtrFactory<HidChooserContext> weak_factory_{this}; 133 }; 134 135 #endif // CHROME_BROWSER_HID_HID_CHOOSER_CONTEXT_H_ 136