blob: 5a42fe2f1dc64000764a6b2781af9f7de6cc1448 [file] [log] [blame]
// 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_