#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;
class DevicePermissionsPrompt {
public:
using UsbDevicesCallback =
base::OnceCallback<void(std::vector<device::mojom::UsbDeviceInfoPtr>)>;
using HidDevicesCallback =
base::OnceCallback<void(std::vector<device::mojom::HidDeviceInfoPtr>)>;
class Prompt : public base::RefCounted<Prompt> {
public:
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;
};
class Observer {
public:
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;
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;
void GrantDevicePermission(size_t index);
virtual void Dismissed() = 0;
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_;
}
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);
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:
raw_ptr<content::WebContents> web_contents_;
scoped_refptr<Prompt> prompt_;
};
}
#endif