
The methodology used to generate this CL is documented in https://crbug.com/1098010#c34. No-Try: true No-Presubmit: true Bug: 1098010 Change-Id: I8c0f009d16350271f07d8e5e561085822cc9dd27 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3895935 Owners-Override: Avi Drissman <avi@chromium.org> Reviewed-by: Mark Mentovai <mark@chromium.org> Commit-Queue: Mark Mentovai <mark@chromium.org> Auto-Submit: Avi Drissman <avi@chromium.org> Cr-Commit-Position: refs/heads/main@{#1047456}
226 lines
8.0 KiB
C++
226 lines
8.0 KiB
C++
// 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.
|
|
|
|
#include "content/web_test/browser/fake_bluetooth_delegate.h"
|
|
|
|
#include "base/containers/contains.h"
|
|
#include "content/public/browser/web_contents.h"
|
|
#include "content/web_test/browser/web_test_control_host.h"
|
|
#include "device/bluetooth/bluetooth_device.h"
|
|
#include "third_party/blink/public/common/bluetooth/web_bluetooth_device_id.h"
|
|
#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h"
|
|
#include "url/origin.h"
|
|
|
|
using blink::WebBluetoothDeviceId;
|
|
using device::BluetoothDevice;
|
|
using device::BluetoothUUID;
|
|
|
|
namespace content {
|
|
|
|
namespace {
|
|
|
|
class AlwaysAllowBluetoothScanning : public BluetoothScanningPrompt {
|
|
public:
|
|
explicit AlwaysAllowBluetoothScanning(const EventHandler& event_handler) {
|
|
event_handler.Run(BluetoothScanningPrompt::Event::kAllow);
|
|
}
|
|
};
|
|
|
|
} // namespace
|
|
|
|
// public
|
|
FakeBluetoothDelegate::FakeBluetoothDelegate() = default;
|
|
FakeBluetoothDelegate::~FakeBluetoothDelegate() = default;
|
|
|
|
std::unique_ptr<BluetoothChooser> FakeBluetoothDelegate::RunBluetoothChooser(
|
|
RenderFrameHost* frame,
|
|
const BluetoothChooser::EventHandler& event_handler) {
|
|
if (auto* web_test_control_host = WebTestControlHost::Get())
|
|
return web_test_control_host->RunBluetoothChooser(frame, event_handler);
|
|
return nullptr;
|
|
}
|
|
|
|
std::unique_ptr<BluetoothScanningPrompt>
|
|
FakeBluetoothDelegate::ShowBluetoothScanningPrompt(
|
|
RenderFrameHost* frame,
|
|
const BluetoothScanningPrompt::EventHandler& event_handler) {
|
|
return std::make_unique<AlwaysAllowBluetoothScanning>(event_handler);
|
|
}
|
|
|
|
void FakeBluetoothDelegate::ShowDevicePairPrompt(
|
|
RenderFrameHost* frame,
|
|
const std::u16string& device_identifier,
|
|
PairPromptCallback callback,
|
|
PairingKind pairing_kind,
|
|
const absl::optional<std::u16string>& pin) {
|
|
std::move(callback).Run(content::BluetoothDelegate::PairPromptResult(
|
|
content::BluetoothDelegate::PairPromptStatus::kCancelled));
|
|
}
|
|
|
|
WebBluetoothDeviceId FakeBluetoothDelegate::GetWebBluetoothDeviceId(
|
|
RenderFrameHost* frame,
|
|
const std::string& device_address) {
|
|
auto& device_address_to_id_map = GetAddressToIdMapForOrigin(frame);
|
|
auto it = device_address_to_id_map.find(device_address);
|
|
if (it != device_address_to_id_map.end())
|
|
return it->second;
|
|
return {};
|
|
}
|
|
|
|
std::string FakeBluetoothDelegate::GetDeviceAddress(
|
|
RenderFrameHost* frame,
|
|
const WebBluetoothDeviceId& device_id) {
|
|
auto& device_address_to_id_map = GetAddressToIdMapForOrigin(frame);
|
|
for (auto& entry : device_address_to_id_map) {
|
|
if (entry.second == device_id)
|
|
return entry.first;
|
|
}
|
|
return std::string();
|
|
}
|
|
|
|
blink::WebBluetoothDeviceId FakeBluetoothDelegate::AddScannedDevice(
|
|
RenderFrameHost* frame,
|
|
const std::string& device_address) {
|
|
return GetOrCreateDeviceIdForDeviceAddress(frame, device_address);
|
|
}
|
|
|
|
WebBluetoothDeviceId FakeBluetoothDelegate::GrantServiceAccessPermission(
|
|
RenderFrameHost* frame,
|
|
const BluetoothDevice* device,
|
|
const blink::mojom::WebBluetoothRequestDeviceOptions* options) {
|
|
WebBluetoothDeviceId device_id =
|
|
GetOrCreateDeviceIdForDeviceAddress(frame, device->GetAddress());
|
|
device_id_to_name_map_[device_id] =
|
|
device->GetName() ? *device->GetName() : std::string();
|
|
GrantUnionOfServicesAndManufacturerDataForDevice(device_id, options);
|
|
return device_id;
|
|
}
|
|
|
|
bool FakeBluetoothDelegate::HasDevicePermission(
|
|
RenderFrameHost* frame,
|
|
const WebBluetoothDeviceId& device_id) {
|
|
return base::Contains(device_id_to_services_map_, device_id);
|
|
}
|
|
|
|
void FakeBluetoothDelegate::RevokeDevicePermissionWebInitiated(
|
|
RenderFrameHost* frame,
|
|
const WebBluetoothDeviceId& device_id) {
|
|
device_id_to_services_map_.erase(device_id);
|
|
device_id_to_name_map_.erase(device_id);
|
|
device_id_to_manufacturer_code_map_.erase(device_id);
|
|
auto& device_address_to_id_map = GetAddressToIdMapForOrigin(frame);
|
|
base::EraseIf(device_address_to_id_map,
|
|
[device_id](auto& entry) { return entry.second == device_id; });
|
|
}
|
|
|
|
bool FakeBluetoothDelegate::IsAllowedToAccessService(
|
|
RenderFrameHost* frame,
|
|
const WebBluetoothDeviceId& device_id,
|
|
const BluetoothUUID& service) {
|
|
auto id_to_services_it = device_id_to_services_map_.find(device_id);
|
|
if (id_to_services_it == device_id_to_services_map_.end())
|
|
return false;
|
|
|
|
return base::Contains(id_to_services_it->second, service);
|
|
}
|
|
|
|
bool FakeBluetoothDelegate::IsAllowedToAccessAtLeastOneService(
|
|
RenderFrameHost* frame,
|
|
const WebBluetoothDeviceId& device_id) {
|
|
auto id_to_services_it = device_id_to_services_map_.find(device_id);
|
|
if (id_to_services_it == device_id_to_services_map_.end())
|
|
return false;
|
|
|
|
return !id_to_services_it->second.empty();
|
|
}
|
|
|
|
bool FakeBluetoothDelegate::IsAllowedToAccessManufacturerData(
|
|
RenderFrameHost* frame,
|
|
const blink::WebBluetoothDeviceId& device_id,
|
|
const uint16_t manufacturer_code) {
|
|
auto id_to_manufacturer_data_it =
|
|
device_id_to_manufacturer_code_map_.find(device_id);
|
|
if (id_to_manufacturer_data_it == device_id_to_manufacturer_code_map_.end())
|
|
return false;
|
|
|
|
return base::Contains(id_to_manufacturer_data_it->second, manufacturer_code);
|
|
}
|
|
|
|
void FakeBluetoothDelegate::AddFramePermissionObserver(
|
|
FramePermissionObserver* observer) {}
|
|
|
|
void FakeBluetoothDelegate::RemoveFramePermissionObserver(
|
|
FramePermissionObserver* observer) {}
|
|
|
|
std::vector<blink::mojom::WebBluetoothDevicePtr>
|
|
FakeBluetoothDelegate::GetPermittedDevices(RenderFrameHost* frame) {
|
|
std::vector<blink::mojom::WebBluetoothDevicePtr> permitted_devices;
|
|
auto& device_address_to_id_map = GetAddressToIdMapForOrigin(frame);
|
|
for (const auto& entry : device_address_to_id_map) {
|
|
auto permitted_device = blink::mojom::WebBluetoothDevice::New();
|
|
WebBluetoothDeviceId device_id = entry.second;
|
|
permitted_device->id = device_id;
|
|
permitted_device->name = device_id_to_name_map_[device_id];
|
|
permitted_devices.push_back(std::move(permitted_device));
|
|
}
|
|
return permitted_devices;
|
|
}
|
|
|
|
WebBluetoothDeviceId FakeBluetoothDelegate::GetOrCreateDeviceIdForDeviceAddress(
|
|
RenderFrameHost* frame,
|
|
const std::string& device_address) {
|
|
WebBluetoothDeviceId device_id;
|
|
auto& device_address_to_id_map = GetAddressToIdMapForOrigin(frame);
|
|
auto it = device_address_to_id_map.find(device_address);
|
|
if (it != device_address_to_id_map.end()) {
|
|
device_id = it->second;
|
|
} else {
|
|
device_id = WebBluetoothDeviceId::Create();
|
|
device_address_to_id_map[device_address] = device_id;
|
|
}
|
|
return device_id;
|
|
}
|
|
|
|
void FakeBluetoothDelegate::GrantUnionOfServicesAndManufacturerDataForDevice(
|
|
const WebBluetoothDeviceId& device_id,
|
|
const blink::mojom::WebBluetoothRequestDeviceOptions* options) {
|
|
if (!options)
|
|
return;
|
|
|
|
// Create an entry for |device_id| in |device_id_to_services_map_| to indicate
|
|
// that the site can attempt to GATT connect even if |options| does not
|
|
// contain any services.
|
|
base::flat_set<BluetoothUUID>& granted_services =
|
|
device_id_to_services_map_[device_id];
|
|
if (options->filters) {
|
|
for (const blink::mojom::WebBluetoothLeScanFilterPtr& filter :
|
|
options->filters.value()) {
|
|
if (!filter->services)
|
|
continue;
|
|
|
|
for (const BluetoothUUID& uuid : filter->services.value())
|
|
granted_services.insert(uuid);
|
|
}
|
|
}
|
|
|
|
for (const BluetoothUUID& uuid : options->optional_services)
|
|
granted_services.insert(uuid);
|
|
|
|
base::flat_set<uint16_t>& granted_manufacturer_data =
|
|
device_id_to_manufacturer_code_map_[device_id];
|
|
for (const uint16_t manufacturer_code : options->optional_manufacturer_data)
|
|
granted_manufacturer_data.insert(manufacturer_code);
|
|
}
|
|
|
|
FakeBluetoothDelegate::AddressToIdMap&
|
|
FakeBluetoothDelegate::GetAddressToIdMapForOrigin(RenderFrameHost* frame) {
|
|
auto* web_contents = WebContents::FromRenderFrameHost(frame);
|
|
auto origin_pair = std::make_pair(
|
|
frame->GetLastCommittedOrigin(),
|
|
web_contents->GetPrimaryMainFrame()->GetLastCommittedOrigin());
|
|
return device_address_to_id_map_for_origin_[origin_pair];
|
|
}
|
|
|
|
} // namespace content
|