feat: add support for Web Bluetooth pin pairing (#35416)
* feat: add bluetooth pairing handler * Update docs/api/session.md Co-authored-by: Charles Kerr <charles@charleskerr.com> * Update docs/api/session.md Co-authored-by: Charles Kerr <charles@charleskerr.com> * docs: update based on review * Apply suggestions from code review Co-authored-by: Erick Zhao <erick@hotmail.ca> Co-authored-by: Charles Kerr <charles@charleskerr.com> * chore: update docs per review * chore: cleanup callback per review Co-authored-by: Charles Kerr <charles@charleskerr.com> Co-authored-by: Erick Zhao <erick@hotmail.ca>
This commit is contained in:
parent
f8077cc004
commit
697a219bcb
11 changed files with 234 additions and 6 deletions
|
@ -7,6 +7,7 @@
|
|||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "build/build_config.h"
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
|
@ -14,7 +15,10 @@
|
|||
#include "device/bluetooth/bluetooth_device.h"
|
||||
#include "device/bluetooth/public/cpp/bluetooth_uuid.h"
|
||||
#include "shell/browser/api/electron_api_web_contents.h"
|
||||
#include "shell/browser/electron_permission_manager.h"
|
||||
#include "shell/browser/lib/bluetooth_chooser.h"
|
||||
#include "shell/common/gin_converters/frame_converter.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
#include "third_party/blink/public/common/bluetooth/web_bluetooth_device_id.h"
|
||||
#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h"
|
||||
|
||||
|
@ -23,6 +27,28 @@ using content::RenderFrameHost;
|
|||
using content::WebContents;
|
||||
using device::BluetoothUUID;
|
||||
|
||||
namespace gin {
|
||||
|
||||
template <>
|
||||
struct Converter<content::BluetoothDelegate::PairingKind> {
|
||||
static v8::Local<v8::Value> ToV8(
|
||||
v8::Isolate* isolate,
|
||||
content::BluetoothDelegate::PairingKind pairing_kind) {
|
||||
switch (pairing_kind) {
|
||||
case content::BluetoothDelegate::PairingKind::kConfirmOnly:
|
||||
return StringToV8(isolate, "confirm");
|
||||
case content::BluetoothDelegate::PairingKind::kConfirmPinMatch:
|
||||
return StringToV8(isolate, "confirmPin");
|
||||
case content::BluetoothDelegate::PairingKind::kProvidePin:
|
||||
return StringToV8(isolate, "providePin");
|
||||
default:
|
||||
return StringToV8(isolate, "unknown");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace gin
|
||||
|
||||
namespace electron {
|
||||
|
||||
ElectronBluetoothDelegate::ElectronBluetoothDelegate() = default;
|
||||
|
@ -136,9 +162,46 @@ void ElectronBluetoothDelegate::ShowDevicePairPrompt(
|
|||
PairPromptCallback callback,
|
||||
PairingKind pairing_kind,
|
||||
const absl::optional<std::u16string>& pin) {
|
||||
NOTIMPLEMENTED();
|
||||
std::move(callback).Run(BluetoothDelegate::PairPromptResult(
|
||||
BluetoothDelegate::PairPromptStatus::kCancelled));
|
||||
auto* web_contents = content::WebContents::FromRenderFrameHost(frame);
|
||||
if (web_contents) {
|
||||
auto* permission_manager = static_cast<ElectronPermissionManager*>(
|
||||
web_contents->GetBrowserContext()->GetPermissionControllerDelegate());
|
||||
|
||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
gin_helper::Dictionary details =
|
||||
gin_helper::Dictionary::CreateEmpty(isolate);
|
||||
details.Set("deviceId", device_identifier);
|
||||
details.Set("pairingKind", pairing_kind);
|
||||
details.SetGetter("frame", frame);
|
||||
if (pin.has_value()) {
|
||||
details.Set("pin", pin.value());
|
||||
}
|
||||
|
||||
permission_manager->CheckBluetoothDevicePair(
|
||||
details, base::AdaptCallbackForRepeating(base::BindOnce(
|
||||
&ElectronBluetoothDelegate::OnDevicePairPromptResponse,
|
||||
weak_factory_.GetWeakPtr(), std::move(callback))));
|
||||
}
|
||||
}
|
||||
|
||||
void ElectronBluetoothDelegate::OnDevicePairPromptResponse(
|
||||
PairPromptCallback callback,
|
||||
base::Value::Dict response) {
|
||||
BluetoothDelegate::PairPromptResult result;
|
||||
if (response.FindBool("confirmed").value_or(false)) {
|
||||
result.result_code = BluetoothDelegate::PairPromptStatus::kSuccess;
|
||||
} else {
|
||||
result.result_code = BluetoothDelegate::PairPromptStatus::kCancelled;
|
||||
}
|
||||
|
||||
const std::string* pin = response.FindString("pin");
|
||||
if (pin) {
|
||||
std::u16string trimmed_input = base::UTF8ToUTF16(*pin);
|
||||
base::TrimWhitespace(trimmed_input, base::TRIM_ALL, &trimmed_input);
|
||||
result.pin = base::UTF16ToUTF8(trimmed_input);
|
||||
}
|
||||
std::move(callback).Run(result);
|
||||
}
|
||||
|
||||
} // namespace electron
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/observer_list.h"
|
||||
#include "base/scoped_observation.h"
|
||||
#include "content/public/browser/bluetooth_delegate.h"
|
||||
|
@ -91,6 +92,12 @@ class ElectronBluetoothDelegate : public content::BluetoothDelegate {
|
|||
void AddFramePermissionObserver(FramePermissionObserver* observer) override;
|
||||
void RemoveFramePermissionObserver(
|
||||
FramePermissionObserver* observer) override;
|
||||
|
||||
private:
|
||||
void OnDevicePairPromptResponse(PairPromptCallback callback,
|
||||
base::Value::Dict response);
|
||||
|
||||
base::WeakPtrFactory<ElectronBluetoothDelegate> weak_factory_{this};
|
||||
};
|
||||
|
||||
} // namespace electron
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue