blob: 29cfaaebd0dd296a5dff264f513dc2471571141e [file] [log] [blame]
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/permissions/bluetooth_delegate_impl.h"
#include "base/observer_list.h"
#include "base/strings/utf_string_conversions.h"
#include "components/permissions/contexts/bluetooth_chooser_context.h"
#include "content/public/browser/render_frame_host.h"
#include "device/bluetooth/bluetooth_device.h"
#include "device/bluetooth/public/cpp/bluetooth_uuid.h"
#include "third_party/blink/public/common/bluetooth/web_bluetooth_device_id.h"
#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h"
using blink::WebBluetoothDeviceId;
using content::RenderFrameHost;
using device::BluetoothUUID;
namespace permissions {
BluetoothDelegateImpl::BluetoothDelegateImpl(std::unique_ptr<Client> client)
: client_(std::move(client)) {}
BluetoothDelegateImpl::~BluetoothDelegateImpl() = default;
std::unique_ptr<content::BluetoothChooser>
BluetoothDelegateImpl::RunBluetoothChooser(
content::RenderFrameHost* frame,
const content::BluetoothChooser::EventHandler& event_handler) {
return client_->RunBluetoothChooser(frame, event_handler);
}
std::unique_ptr<content::BluetoothScanningPrompt>
BluetoothDelegateImpl::ShowBluetoothScanningPrompt(
content::RenderFrameHost* frame,
const content::BluetoothScanningPrompt::EventHandler& event_handler) {
return client_->ShowBluetoothScanningPrompt(frame, event_handler);
}
void BluetoothDelegateImpl::ShowDeviceCredentialsPrompt(
RenderFrameHost* frame,
const std::u16string& device_identifier,
CredentialsCallback callback) {
client_->ShowBluetoothDeviceCredentialsDialog(frame, device_identifier,
std::move(callback));
}
WebBluetoothDeviceId BluetoothDelegateImpl::GetWebBluetoothDeviceId(
RenderFrameHost* frame,
const std::string& device_address) {
return client_->GetBluetoothChooserContext(frame)->GetWebBluetoothDeviceId(
frame->GetMainFrame()->GetLastCommittedOrigin(), device_address);
}
std::string BluetoothDelegateImpl::GetDeviceAddress(
RenderFrameHost* frame,
const WebBluetoothDeviceId& device_id) {
return client_->GetBluetoothChooserContext(frame)->GetDeviceAddress(
frame->GetMainFrame()->GetLastCommittedOrigin(), device_id);
}
WebBluetoothDeviceId BluetoothDelegateImpl::AddScannedDevice(
RenderFrameHost* frame,
const std::string& device_address) {
return client_->GetBluetoothChooserContext(frame)->AddScannedDevice(
frame->GetMainFrame()->GetLastCommittedOrigin(), device_address);
}
WebBluetoothDeviceId BluetoothDelegateImpl::GrantServiceAccessPermission(
RenderFrameHost* frame,
const device::BluetoothDevice* device,
const blink::mojom::WebBluetoothRequestDeviceOptions* options) {
return client_->GetBluetoothChooserContext(frame)
->GrantServiceAccessPermission(
frame->GetMainFrame()->GetLastCommittedOrigin(), device, options);
}
bool BluetoothDelegateImpl::HasDevicePermission(
RenderFrameHost* frame,
const WebBluetoothDeviceId& device_id) {
return client_->GetBluetoothChooserContext(frame)->HasDevicePermission(
frame->GetMainFrame()->GetLastCommittedOrigin(), device_id);
}
void BluetoothDelegateImpl::RevokeDevicePermissionWebInitiated(
RenderFrameHost* frame,
const WebBluetoothDeviceId& device_id) {
client_->GetBluetoothChooserContext(frame)
->RevokeDevicePermissionWebInitiated(
frame->GetMainFrame()->GetLastCommittedOrigin(), device_id);
}
bool BluetoothDelegateImpl::IsAllowedToAccessService(
RenderFrameHost* frame,
const WebBluetoothDeviceId& device_id,
const BluetoothUUID& service) {
return client_->GetBluetoothChooserContext(frame)->IsAllowedToAccessService(
frame->GetMainFrame()->GetLastCommittedOrigin(), device_id, service);
}
bool BluetoothDelegateImpl::IsAllowedToAccessAtLeastOneService(
RenderFrameHost* frame,
const WebBluetoothDeviceId& device_id) {
return client_->GetBluetoothChooserContext(frame)
->IsAllowedToAccessAtLeastOneService(
frame->GetMainFrame()->GetLastCommittedOrigin(), device_id);
}
bool BluetoothDelegateImpl::IsAllowedToAccessManufacturerData(
RenderFrameHost* frame,
const WebBluetoothDeviceId& device_id,
uint16_t manufacturer_code) {
return client_->GetBluetoothChooserContext(frame)
->IsAllowedToAccessManufacturerData(
frame->GetMainFrame()->GetLastCommittedOrigin(), device_id,
manufacturer_code);
}
void BluetoothDelegateImpl::AddFramePermissionObserver(
FramePermissionObserver* observer) {
std::unique_ptr<ChooserContextPermissionObserver>& chooser_observer =
chooser_observers_[observer->GetRenderFrameHost()];
if (!chooser_observer) {
chooser_observer = std::make_unique<ChooserContextPermissionObserver>(
this,
client_->GetBluetoothChooserContext(observer->GetRenderFrameHost()));
}
chooser_observer->AddFramePermissionObserver(observer);
}
void BluetoothDelegateImpl::RemoveFramePermissionObserver(
FramePermissionObserver* observer) {
auto it = chooser_observers_.find(observer->GetRenderFrameHost());
if (it == chooser_observers_.end())
return;
it->second->RemoveFramePermissionObserver(observer);
}
std::vector<blink::mojom::WebBluetoothDevicePtr>
BluetoothDelegateImpl::GetPermittedDevices(content::RenderFrameHost* frame) {
auto* context = client_->GetBluetoothChooserContext(frame);
std::vector<std::unique_ptr<ObjectPermissionContextBase::Object>> objects =
context->GetGrantedObjects(
frame->GetMainFrame()->GetLastCommittedOrigin());
std::vector<blink::mojom::WebBluetoothDevicePtr> permitted_devices;
for (const auto& object : objects) {
auto permitted_device = blink::mojom::WebBluetoothDevice::New();
permitted_device->id =
BluetoothChooserContext::GetObjectDeviceId(object->value);
permitted_device->name =
base::UTF16ToUTF8(context->GetObjectDisplayName(object->value));
permitted_devices.push_back(std::move(permitted_device));
}
return permitted_devices;
}
BluetoothDelegateImpl::ChooserContextPermissionObserver::
ChooserContextPermissionObserver(BluetoothDelegateImpl* owning_delegate,
ObjectPermissionContextBase* context)
: owning_delegate_(owning_delegate) {
observer_.Observe(context);
}
BluetoothDelegateImpl::ChooserContextPermissionObserver::
~ChooserContextPermissionObserver() = default;
void BluetoothDelegateImpl::ChooserContextPermissionObserver::
OnPermissionRevoked(const url::Origin& origin) {
observers_pending_removal_.clear();
is_traversing_observers_ = true;
for (auto& observer : observer_list_)
observer.OnPermissionRevoked(origin);
is_traversing_observers_ = false;
for (FramePermissionObserver* observer : observers_pending_removal_)
RemoveFramePermissionObserver(observer);
}
void BluetoothDelegateImpl::ChooserContextPermissionObserver::
AddFramePermissionObserver(FramePermissionObserver* observer) {
observer_list_.AddObserver(observer);
}
void BluetoothDelegateImpl::ChooserContextPermissionObserver::
RemoveFramePermissionObserver(FramePermissionObserver* observer) {
if (is_traversing_observers_) {
observers_pending_removal_.emplace_back(observer);
return;
}
observer_list_.RemoveObserver(observer);
if (observer_list_.empty())
owning_delegate_->chooser_observers_.erase(observer->GetRenderFrameHost());
// Previous call destructed this instance. Don't add code after this.
}
} // namespace permissions