1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
content / public / browser / bluetooth_delegate.h [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_PUBLIC_BROWSER_BLUETOOTH_DELEGATE_H_
#define CONTENT_PUBLIC_BROWSER_BLUETOOTH_DELEGATE_H_
#include <string>
#include <vector>
#include "base/observer_list_types.h"
#include "base/scoped_observation_traits.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
#include "content/public/browser/bluetooth_chooser.h"
#include "content/public/browser/bluetooth_scanning_prompt.h"
#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-forward.h"
#include "url/origin.h"
// Some OS Bluetooth stacks (macOS and Android) automatically bond to a device
// when accessing a characteristic/descriptor which requires an authenticated
// client. For other platforms Chrome does the on-demand pairing.
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX)
#define PAIR_BLUETOOTH_ON_DEMAND() true
#else
#define PAIR_BLUETOOTH_ON_DEMAND() false
#endif
namespace blink {
class WebBluetoothDeviceId;
} // namespace blink
namespace device {
class BluetoothDevice;
class BluetoothUUID;
} // namespace device
namespace content {
class RenderFrameHost;
// Provides an interface for managing device permissions for Web Bluetooth and
// Web Bluetooth Scanning API. An embedder may implement this to manage these
// permissions.
// TODO(crbug.com/40117221): There are several Bluetooth related methods
// in WebContentsDelegate and ContentBrowserClient that can be moved into this
// class.
class CONTENT_EXPORT BluetoothDelegate {
public:
// The result of the prompt when requesting device pairing
// from the user.
enum class PairPromptStatus {
kSuccess, // Result contains user credentials.
kCancelled, // User cancelled, or agent cancelled on their behalf.
};
// Based on the pairing kinds defined by Windows but it also applies to any
// platform on which we support manual pairing through |PairingDelegate| Ref:
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicepairingkinds?view=winrt-22621
enum class PairingKind {
kConfirmOnly,
kConfirmPinMatch,
kDisplayPin,
kProvidePasswordCredential,
kProvidePin
};
// Struct for pairing prompt result, include |pairing_kind| or |pin| or other
// needed fields added in future all other fieds should be meaniningful only
// if |result_code| is |kSuccess|
struct PairPromptResult {
PairPromptResult() = default;
explicit PairPromptResult(PairPromptStatus code) : result_code(code) {}
~PairPromptResult() = default;
PairPromptStatus result_code = PairPromptStatus::kCancelled;
std::string pin;
};
using PairPromptCallback =
base::OnceCallback<void(const PairPromptResult& result)>;
// An observer used to track permission revocation events for a particular
// RenderFrameHost.
class CONTENT_EXPORT FramePermissionObserver : public base::CheckedObserver {
public:
// Notify observer that an object permission was revoked for |origin|.
virtual void OnPermissionRevoked(const url::Origin& origin) = 0;
// Returns the frame that the observer wishes to watch.
virtual RenderFrameHost* GetRenderFrameHost() = 0;
};
virtual ~BluetoothDelegate() = default;
// Shows a chooser for the user to select a nearby Bluetooth device. The
// EventHandler should live at least as long as the returned chooser object.
virtual std::unique_ptr<BluetoothChooser> RunBluetoothChooser(
RenderFrameHost* frame,
const BluetoothChooser::EventHandler& event_handler) = 0;
// Shows a prompt for the user to allow/block Bluetooth scanning. The
// EventHandler should live at least as long as the returned prompt object.
virtual std::unique_ptr<BluetoothScanningPrompt> ShowBluetoothScanningPrompt(
RenderFrameHost* frame,
const BluetoothScanningPrompt::EventHandler& event_handler) = 0;
// Prompt the user (via dialog, etc.) for pairing Bluetooth device
// |device_identifier| is any string the caller wants to display
// to the user to identify the device (MAC address, name, etc.). |callback|
// will be called with the prompt result. |callback| may be called immediately
// from this function, for example, if a credential prompt for the given
// |frame| is already displayed.
// |pairing_kind| is to determine which pairing kind of prompt to be created
virtual void ShowDevicePairPrompt(
RenderFrameHost* frame,
const std::u16string& device_identifier,
PairPromptCallback callback,
PairingKind pairing_kind,
const std::optional<std::u16string>& pin) = 0;
// This should return the WebBluetoothDeviceId that corresponds to the device
// with |device_address| in the current |frame|. If there is not a
// corresponding ID, then an invalid WebBluetoothDeviceId should be returned.
virtual blink::WebBluetoothDeviceId GetWebBluetoothDeviceId(
RenderFrameHost* frame,
const std::string& device_address) = 0;
// This should return the device address corresponding to a device with
// |device_id| in the current |frame|. If there is not a corresponding
// address, then an empty string should be returned.
virtual std::string GetDeviceAddress(
RenderFrameHost* frame,
const blink::WebBluetoothDeviceId& device_id) = 0;
// This should return the WebBluetoothDeviceId for |device_address| if the
// device has been assigned an ID previously through AddScannedDevice() or
// GrantServiceAccessPermission(). If not, a new ID should be generated for
// |device_address| and stored in a temporary map of address to ID. Service
// access should not be granted to these devices.
virtual blink::WebBluetoothDeviceId AddScannedDevice(
RenderFrameHost* frame,
const std::string& device_address) = 0;
// This should grant permission to the requesting and embedding origins
// represented by |frame| to connect to the device with |device_address| and
// access its |services|. Once permission is granted, a |WebBluetoothDeviceId|
// should be generated for the device and returned.
virtual blink::WebBluetoothDeviceId GrantServiceAccessPermission(
RenderFrameHost* frame,
const device::BluetoothDevice* device,
const blink::mojom::WebBluetoothRequestDeviceOptions* options) = 0;
// This should return true if |frame| has been granted permission to access
// the device with |device_id| through GrantServiceAccessPermission().
// |device_id|s generated with AddScannedDevices() should return false.
virtual bool HasDevicePermission(
RenderFrameHost* frame,
const blink::WebBluetoothDeviceId& device_id) = 0;
// Revokes |frame| access to the Bluetooth device ordered by website.
virtual void RevokeDevicePermissionWebInitiated(
RenderFrameHost* frame,
const blink::WebBluetoothDeviceId& device_id) = 0;
// This should return true if |frame| is allowed to use bluetooth.
virtual bool MayUseBluetooth(RenderFrameHost* frame) = 0;
// This should return true if |frame| has permission to access |service| from
// the device with |device_id|.
virtual bool IsAllowedToAccessService(
RenderFrameHost* frame,
const blink::WebBluetoothDeviceId& device_id,
const device::BluetoothUUID& service) = 0;
// This should return true if |frame| can access at least one service from the
// device with |device_id|.
virtual bool IsAllowedToAccessAtLeastOneService(
RenderFrameHost* frame,
const blink::WebBluetoothDeviceId& device_id) = 0;
// This should return true if |frame| has permission to access data associated
// with |manufacturer_code| from advertisement packets from the device with
// |device_id|.
virtual bool IsAllowedToAccessManufacturerData(
RenderFrameHost* frame,
const blink::WebBluetoothDeviceId& device_id,
uint16_t manufacturer_code) = 0;
// This should return a list of devices that the origin in |frame| has been
// allowed to access. Access permission is granted with
// GrantServiceAccessPermission() and can be revoked by the user in the
// embedder's UI. The list of devices returned should be PermittedDevice
// objects, which contain the necessary fields to create the BluetoothDevice
// JavaScript objects.
virtual std::vector<blink::mojom::WebBluetoothDevicePtr> GetPermittedDevices(
RenderFrameHost* frame) = 0;
// Add a permission observer to allow observing permission revocation effects
// for a particular frame.
virtual void AddFramePermissionObserver(
FramePermissionObserver* observer) = 0;
// Remove a previously added permission observer.
virtual void RemoveFramePermissionObserver(
FramePermissionObserver* observer) = 0;
};
} // namespace content
namespace base {
template <>
struct ScopedObservationTraits<
content::BluetoothDelegate,
content::BluetoothDelegate::FramePermissionObserver> {
static void AddObserver(
content::BluetoothDelegate* source,
content::BluetoothDelegate::FramePermissionObserver* observer) {
source->AddFramePermissionObserver(observer);
}
static void RemoveObserver(
content::BluetoothDelegate* source,
content::BluetoothDelegate::FramePermissionObserver* observer) {
source->RemoveFramePermissionObserver(observer);
}
};
} // namespace base
#endif // CONTENT_PUBLIC_BROWSER_BLUETOOTH_DELEGATE_H_