Commit e27db6b0 authored by Jun Cai's avatar Jun Cai Committed by Commit Bot

Bluetooth Scanning API: Revoke granted permission when tab is switched to background

This CL implements revoking previously granted permission for Bluetooth Scanning API
when a tab is switched to background.

Design doc:
https://docs.google.com/document/d/1k4WM56Dx7sCu2k2MjvOdXArNz2Dy8BA1vt2VYHA6v7A/edit

Bug: 953075
Change-Id: I6690dcab7bfe8b41162cb3d1c98f8c18863955ba
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1614423
Commit-Queue: Jun Cai <juncai@chromium.org>
Reviewed-by: default avatarReilly Grant <reillyg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#666157}
parent 852d5960
......@@ -410,6 +410,15 @@ void WebBluetoothServiceImpl::DidFinishNavigation(
}
}
void WebBluetoothServiceImpl::OnVisibilityChanged(Visibility visibility) {
if (visibility == content::Visibility::HIDDEN ||
visibility == content::Visibility::OCCLUDED) {
allowed_scan_filters_.clear();
accept_all_advertisements_ = false;
scanning_clients_.clear();
}
}
void WebBluetoothServiceImpl::AdapterPoweredChanged(
device::BluetoothAdapter* adapter,
bool powered) {
......
......@@ -9,6 +9,7 @@
#include <string>
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/optional.h"
#include "content/browser/bad_message.h"
......@@ -81,7 +82,12 @@ class CONTENT_EXPORT WebBluetoothServiceImpl
BluetoothDeviceScanningPromptController* prompt_controller);
private:
FRIEND_TEST_ALL_PREFIXES(WebBluetoothServiceImplTest,
BluetoothScanningPermissionRevokedWhenTabHidden);
FRIEND_TEST_ALL_PREFIXES(WebBluetoothServiceImplTest,
BluetoothScanningPermissionRevokedWhenTabOccluded);
friend class FrameConnectedBluetoothDevicesTest;
friend class WebBluetoothServiceImplTest;
using PrimaryServicesRequestCallback =
base::OnceCallback<void(device::BluetoothDevice*)>;
using ScanFilters = std::vector<blink::mojom::WebBluetoothLeScanFilterPtr>;
......@@ -133,6 +139,7 @@ class CONTENT_EXPORT WebBluetoothServiceImpl
// These functions should always check that the affected RenderFrameHost
// is this->render_frame_host_ and not some other frame in the same tab.
void DidFinishNavigation(NavigationHandle* navigation_handle) override;
void OnVisibilityChanged(Visibility visibility) override;
// BluetoothAdapter::Observer:
void AdapterPoweredChanged(device::BluetoothAdapter* adapter,
......
// Copyright 2019 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 "content/browser/bluetooth/web_bluetooth_service_impl.h"
#include "base/macros.h"
#include "base/test/bind_test_util.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "device/bluetooth/bluetooth_adapter_factory_wrapper.h"
#include "device/bluetooth/test/mock_bluetooth_adapter.h"
#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::Return;
namespace content {
namespace {
const char kBatteryServiceUUIDString[] = "0000180f-0000-1000-8000-00805f9b34fb";
class FakeBluetoothScanningPrompt : public BluetoothScanningPrompt {
public:
explicit FakeBluetoothScanningPrompt(const EventHandler& event_handler) {
event_handler.Run(content::BluetoothScanningPrompt::Event::kAllow);
}
~FakeBluetoothScanningPrompt() override = default;
private:
DISALLOW_COPY_AND_ASSIGN(FakeBluetoothScanningPrompt);
};
class FakeBluetoothAdapter : public device::MockBluetoothAdapter {
public:
FakeBluetoothAdapter() = default;
// device::BluetoothAdapter:
void StartScanWithFilter(
std::unique_ptr<device::BluetoothDiscoveryFilter> discovery_filter,
DiscoverySessionResultCallback callback) override {
std::move(callback).Run(
/*is_error=*/false,
device::UMABluetoothDiscoverySessionOutcome::SUCCESS);
}
protected:
~FakeBluetoothAdapter() override = default;
private:
DISALLOW_COPY_AND_ASSIGN(FakeBluetoothAdapter);
};
class FakeWebContentsDelegate : public content::WebContentsDelegate {
public:
FakeWebContentsDelegate() = default;
~FakeWebContentsDelegate() override = default;
std::unique_ptr<BluetoothScanningPrompt> ShowBluetoothScanningPrompt(
RenderFrameHost* frame,
const BluetoothScanningPrompt::EventHandler& event_handler) override {
return std::make_unique<FakeBluetoothScanningPrompt>(event_handler);
}
private:
DISALLOW_COPY_AND_ASSIGN(FakeWebContentsDelegate);
};
} // namespace
class WebBluetoothServiceImplTest : public RenderViewHostImplTestHarness {
public:
WebBluetoothServiceImplTest() = default;
~WebBluetoothServiceImplTest() override = default;
void SetUp() override {
RenderViewHostImplTestHarness::SetUp();
// Set up an adapter.
scoped_refptr<FakeBluetoothAdapter> adapter(new FakeBluetoothAdapter());
EXPECT_CALL(*adapter, IsPresent()).WillRepeatedly(Return(true));
device::BluetoothAdapterFactoryWrapper::Get().SetBluetoothAdapterForTesting(
adapter);
contents()->GetMainFrame()->InitializeRenderFrameIfNeeded();
contents()->SetDelegate(&delegate_);
// Simulate a frame connected to a bluetooth service.
service_ =
contents()->GetMainFrame()->CreateWebBluetoothServiceForTesting();
blink::mojom::WebBluetoothScanClientAssociatedPtrInfo client_info;
mojo::MakeRequest(&client_info);
auto options = blink::mojom::WebBluetoothRequestLEScanOptions::New();
base::Optional<std::vector<device::BluetoothUUID>> services;
services.emplace();
services->push_back(device::BluetoothUUID(kBatteryServiceUUIDString));
auto filter =
blink::mojom::WebBluetoothLeScanFilter::New(services, "a", "b");
options->filters.emplace();
options->filters->push_back(filter.Clone());
filters_.emplace();
filters_->push_back(filter.Clone());
service_->RequestScanningStart(
std::move(client_info), std::move(options),
base::BindLambdaForTesting(
[&](blink::mojom::RequestScanningStartResultPtr p) {
loop_.Quit();
}));
loop_.Run();
}
void TearDown() override {
service_ = nullptr;
RenderViewHostImplTestHarness::TearDown();
}
protected:
WebBluetoothServiceImpl* service_;
base::Optional<WebBluetoothServiceImpl::ScanFilters> filters_;
FakeWebContentsDelegate delegate_;
base::RunLoop loop_;
private:
DISALLOW_COPY_AND_ASSIGN(WebBluetoothServiceImplTest);
};
TEST_F(WebBluetoothServiceImplTest,
BluetoothScanningPermissionRevokedWhenTabHidden) {
EXPECT_TRUE(service_->AreScanFiltersAllowed(filters_));
contents()->SetVisibility(content::Visibility::HIDDEN);
// The previously granted Bluetooth scanning permission should be revoked.
EXPECT_FALSE(service_->AreScanFiltersAllowed(filters_));
}
TEST_F(WebBluetoothServiceImplTest,
BluetoothScanningPermissionRevokedWhenTabOccluded) {
EXPECT_TRUE(service_->AreScanFiltersAllowed(filters_));
contents()->SetVisibility(content::Visibility::OCCLUDED);
// The previously granted Bluetooth scanning permission should be revoked.
EXPECT_FALSE(service_->AreScanFiltersAllowed(filters_));
}
} // namespace content
......@@ -1441,6 +1441,7 @@ test("content_unittests") {
"../browser/bluetooth/bluetooth_device_chooser_controller_unittest.cc",
"../browser/bluetooth/bluetooth_util_unittest.cc",
"../browser/bluetooth/frame_connected_bluetooth_devices_unittest.cc",
"../browser/bluetooth/web_bluetooth_service_impl_unittest.cc",
"../browser/browser_associated_interface_unittest.cc",
"../browser/browser_main_loop_unittest.cc",
"../browser/browser_thread_unittest.cc",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment