| // Copyright 2014 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_DEVICE_PERMISSIONS_PROMPT_H_ |
| #define EXTENSIONS_BROWSER_API_DEVICE_PERMISSIONS_PROMPT_H_ |
| |
| #include <stddef.h> |
| |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include "base/functional/callback_forward.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/ref_counted.h" |
| #include "mojo/public/cpp/bindings/pending_receiver.h" |
| #include "services/device/public/mojom/hid.mojom.h" |
| #include "services/device/public/mojom/usb_device.mojom.h" |
| #include "services/device/public/mojom/usb_manager.mojom.h" |
| |
| namespace content { |
| class BrowserContext; |
| class WebContents; |
| } |
| |
| namespace device { |
| class HidDeviceFilter; |
| } |
| |
| namespace extensions { |
| |
| class Extension; |
| |
| // Platform-independent interface for displaing a UI for choosing devices |
| // (similar to choosing files). |
| class DevicePermissionsPrompt { |
| public: |
| using UsbDevicesCallback = |
| base::OnceCallback<void(std::vector<device::mojom::UsbDeviceInfoPtr>)>; |
| using HidDevicesCallback = |
| base::OnceCallback<void(std::vector<device::mojom::HidDeviceInfoPtr>)>; |
| |
| // Context information available to the UI implementation. |
| class Prompt : public base::RefCounted<Prompt> { |
| public: |
| // This class stores the device information displayed in the UI. It should |
| // be extended to support particular device types. |
| class DeviceInfo { |
| public: |
| DeviceInfo(); |
| virtual ~DeviceInfo(); |
| |
| const std::u16string& name() const { return name_; } |
| const std::u16string& serial_number() const { return serial_number_; } |
| bool granted() const { return granted_; } |
| void set_granted() { granted_ = true; } |
| |
| protected: |
| std::u16string name_; |
| std::u16string serial_number_; |
| |
| private: |
| bool granted_ = false; |
| }; |
| |
| // Since the set of devices can change while the UI is visible an |
| // implementation should register an observer. |
| class Observer { |
| public: |
| // Must be called after OnDeviceAdded() has been called for the final time |
| // to create the initial set of options. |
| virtual void OnDevicesInitialized() = 0; |
| virtual void OnDeviceAdded(size_t index, |
| const std::u16string& device_name) = 0; |
| virtual void OnDeviceRemoved(size_t index, |
| const std::u16string& device_name) = 0; |
| |
| protected: |
| virtual ~Observer(); |
| }; |
| |
| Prompt(const Extension* extension, |
| content::BrowserContext* context, |
| bool multiple); |
| |
| Prompt(const Prompt&) = delete; |
| Prompt& operator=(const Prompt&) = delete; |
| |
| // Only one observer may be registered at a time. |
| virtual void SetObserver(Observer* observer); |
| |
| size_t GetDeviceCount() const { return devices_.size(); } |
| std::u16string GetDeviceName(size_t index) const; |
| std::u16string GetDeviceSerialNumber(size_t index) const; |
| |
| // Notifies the DevicePermissionsManager for the current extension that |
| // access to the device at the given index is now granted. |
| void GrantDevicePermission(size_t index); |
| |
| virtual void Dismissed() = 0; |
| |
| // Allow the user to select multiple devices. |
| bool multiple() const { return multiple_; } |
| |
| protected: |
| virtual ~Prompt(); |
| |
| void AddDevice(std::unique_ptr<DeviceInfo> device); |
| |
| const Extension* extension() const { return extension_; } |
| Observer* observer() const { return observer_; } |
| content::BrowserContext* browser_context() const { |
| return browser_context_; |
| } |
| |
| // Subclasses may fill this with a particular subclass of DeviceInfo and may |
| // assume that only that instances of that type are stored here. |
| std::vector<std::unique_ptr<DeviceInfo>> devices_; |
| |
| private: |
| friend class base::RefCounted<Prompt>; |
| |
| raw_ptr<const extensions::Extension, DanglingUntriaged> extension_ = |
| nullptr; |
| raw_ptr<Observer, DanglingUntriaged> observer_ = nullptr; |
| raw_ptr<content::BrowserContext, DanglingUntriaged> browser_context_ = |
| nullptr; |
| bool multiple_ = false; |
| }; |
| |
| explicit DevicePermissionsPrompt(content::WebContents* web_contents); |
| |
| DevicePermissionsPrompt(const DevicePermissionsPrompt&) = delete; |
| DevicePermissionsPrompt& operator=(const DevicePermissionsPrompt&) = delete; |
| |
| virtual ~DevicePermissionsPrompt(); |
| |
| void AskForUsbDevices(const Extension* extension, |
| content::BrowserContext* context, |
| bool multiple, |
| std::vector<device::mojom::UsbDeviceFilterPtr> filters, |
| UsbDevicesCallback callback); |
| |
| void AskForHidDevices(const Extension* extension, |
| content::BrowserContext* context, |
| bool multiple, |
| const std::vector<device::HidDeviceFilter>& filters, |
| HidDevicesCallback callback); |
| |
| static scoped_refptr<Prompt> CreateHidPromptForTest( |
| const Extension* extension, |
| bool multiple); |
| static scoped_refptr<Prompt> CreateUsbPromptForTest( |
| const Extension* extension, |
| bool multiple); |
| |
| // Allows tests to override how the HidManager interface is bound. |
| using HidManagerBinder = base::RepeatingCallback<void( |
| mojo::PendingReceiver<device::mojom::HidManager> receiver)>; |
| static void OverrideHidManagerBinderForTesting(HidManagerBinder binder); |
| |
| protected: |
| virtual void ShowDialog() = 0; |
| |
| content::WebContents* web_contents() { return web_contents_; } |
| scoped_refptr<Prompt> prompt() { return prompt_; } |
| |
| private: |
| // Parent web contents of the device permissions UI dialog. |
| raw_ptr<content::WebContents> web_contents_; |
| |
| // Parameters available to the UI implementation. |
| scoped_refptr<Prompt> prompt_; |
| }; |
| |
| } // namespace extensions |
| |
| #endif // EXTENSIONS_BROWSER_API_DEVICE_PERMISSIONS_PROMPT_H_ |