// 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_(std::move(client)) {} BluetoothDelegateImpl::~BluetoothDelegateImpl() = default; std::unique_ptr BluetoothDelegateImpl::RunBluetoothChooser( content::RenderFrameHost* frame, const content::BluetoothChooser::EventHandler& event_handler) { return client_->RunBluetoothChooser(frame, event_handler); } std::unique_ptr BluetoothDelegateImpl::ShowBluetoothScanningPrompt( content::RenderFrameHost* frame, const content::BluetoothScanningPrompt::EventHandler& event_handler) { return client_->ShowBluetoothScanningPrompt(frame, event_handler); } void BluetoothDelegateImpl::ShowDevicePairPrompt( RenderFrameHost* frame, const std::u16string& device_identifier, PairPromptCallback callback, PairingKind pairing_kind, const absl::optional& pin) { client_->ShowBluetoothDevicePairDialog( frame, device_identifier, std::move(callback), pairing_kind, pin); } 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& chooser_observer = chooser_observers_[observer->GetRenderFrameHost()]; if (!chooser_observer) { chooser_observer = std::make_unique( 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 BluetoothDelegateImpl::GetPermittedDevices(content::RenderFrameHost* frame) { auto* context = client_->GetBluetoothChooserContext(frame); std::vector> objects = context->GetGrantedObjects( frame->GetMainFrame()->GetLastCommittedOrigin()); std::vector 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