diff options
author | jyasskin <jyasskin@chromium.org> | 2015-11-18 11:55:37 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-11-18 19:56:42 +0000 |
commit | 97ef21ed61bb27be090f0881db69b72e68047889 (patch) | |
tree | 51d5be34c43c78f36ba1e358ee9c04d3f22d9e7f | |
parent | 93e85639793d75edf25077db51d28f5403d56736 (diff) | |
download | chromium_src-97ef21ed61bb27be090f0881db69b72e68047889.zip chromium_src-97ef21ed61bb27be090f0881db69b72e68047889.tar.gz chromium_src-97ef21ed61bb27be090f0881db69b72e68047889.tar.bz2 |
Test that device/bluetooth fails to scan on Android when denied permission.
BUG=511805
Review URL: https://codereview.chromium.org/1454573003
Cr-Commit-Position: refs/heads/master@{#360395}
8 files changed, 104 insertions, 28 deletions
diff --git a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothAdapter.java b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothAdapter.java index c06d032..0774ea2 100644 --- a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothAdapter.java +++ b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothAdapter.java @@ -4,6 +4,7 @@ package org.chromium.device.bluetooth; +import android.Manifest; import android.annotation.TargetApi; import android.bluetooth.BluetoothAdapter; import android.bluetooth.le.ScanSettings; @@ -168,13 +169,22 @@ final class ChromeBluetoothAdapter { // Implementation details: /** + * @return true if Chromium has permission to scan for Bluetooth devices. + */ + private boolean canScan() { + Wrappers.ContextWrapper context = mAdapter.getContext(); + return context.checkPermission(Manifest.permission.ACCESS_COARSE_LOCATION) + || context.checkPermission(Manifest.permission.ACCESS_FINE_LOCATION); + } + + /** * Starts a Low Energy scan. * @return True on success. */ private boolean startScan() { Wrappers.BluetoothLeScannerWrapper scanner = mAdapter.getBluetoothLeScanner(); - if (!scanner.canScan()) { + if (!canScan()) { return false; } diff --git a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/Wrappers.java b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/Wrappers.java index 4e67049..56e9e7e 100644 --- a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/Wrappers.java +++ b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/Wrappers.java @@ -50,6 +50,7 @@ class Wrappers { */ static class BluetoothAdapterWrapper { private final BluetoothAdapter mAdapter; + protected final ContextWrapper mContext; protected final BluetoothLeScannerWrapper mScanner; /** @@ -92,17 +93,22 @@ class Wrappers { Log.i(TAG, "BluetoothAdapterWrapper.create failed: Default adapter not found."); return null; } else { - return new BluetoothAdapterWrapper(adapter, - new BluetoothLeScannerWrapper(context, adapter.getBluetoothLeScanner())); + return new BluetoothAdapterWrapper(adapter, new ContextWrapper(context), + new BluetoothLeScannerWrapper(adapter.getBluetoothLeScanner())); } } - public BluetoothAdapterWrapper( - BluetoothAdapter adapter, BluetoothLeScannerWrapper scanner) { + public BluetoothAdapterWrapper(BluetoothAdapter adapter, ContextWrapper context, + BluetoothLeScannerWrapper scanner) { mAdapter = adapter; + mContext = context; mScanner = scanner; } + public ContextWrapper getContext() { + return mContext; + } + public BluetoothLeScannerWrapper getBluetoothLeScanner() { return mScanner; } @@ -129,31 +135,33 @@ class Wrappers { } /** + * Wraps android.content.Context. + */ + static class ContextWrapper { + private final Context mContext; + + public ContextWrapper(Context context) { + mContext = context; + } + + public boolean checkPermission(String permission) { + return mContext.checkPermission(permission, Process.myPid(), Process.myUid()) + == PackageManager.PERMISSION_GRANTED; + } + } + + /** * Wraps android.bluetooth.BluetoothLeScanner. */ static class BluetoothLeScannerWrapper { - private final Context mContext; private final BluetoothLeScanner mScanner; private final HashMap<ScanCallbackWrapper, ForwardScanCallbackToWrapper> mCallbacks; - public BluetoothLeScannerWrapper(Context context, BluetoothLeScanner scanner) { - mContext = context; + public BluetoothLeScannerWrapper(BluetoothLeScanner scanner) { mScanner = scanner; mCallbacks = new HashMap<ScanCallbackWrapper, ForwardScanCallbackToWrapper>(); } - // Returns true if we have permission to get results from a scan. - public boolean canScan() { - int myPid = Process.myPid(); - int myUid = Process.myUid(); - return mContext.checkPermission( - Manifest.permission.ACCESS_COARSE_LOCATION, myPid, myUid) - == PackageManager.PERMISSION_GRANTED - || mContext.checkPermission( - Manifest.permission.ACCESS_FINE_LOCATION, myPid, myUid) - == PackageManager.PERMISSION_GRANTED; - } - public void startScan( List<ScanFilter> filters, int scanSettingsScanMode, ScanCallbackWrapper callback) { ScanSettings settings = diff --git a/device/bluetooth/bluetooth_adapter_unittest.cc b/device/bluetooth/bluetooth_adapter_unittest.cc index fccb128..8b7f86f 100644 --- a/device/bluetooth/bluetooth_adapter_unittest.cc +++ b/device/bluetooth/bluetooth_adapter_unittest.cc @@ -474,6 +474,28 @@ TEST_F(BluetoothTest, DiscoverySession) { #endif // defined(OS_ANDROID) #if defined(OS_ANDROID) || defined(OS_MACOSX) +// Checks that discovery fails (instead of hanging) when permissions are denied. +TEST_F(BluetoothTest, NoPermissions) { + if (!PlatformSupportsLowEnergy()) { + LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test."; + return; + } + InitWithFakeAdapter(); + TestBluetoothAdapterObserver observer(adapter_); + + if (!DenyPermission()) { + // Platform always gives permission to scan. + return; + } + + StartLowEnergyDiscoverySession(); + + EXPECT_EQ(0, callback_count_); + EXPECT_EQ(1, error_callback_count_); +} +#endif // defined(OS_ANDROID) || defined(OS_MACOSX) + +#if defined(OS_ANDROID) || defined(OS_MACOSX) // Discovers a device. TEST_F(BluetoothTest, DiscoverLowEnergyDevice) { if (!PlatformSupportsLowEnergy()) { diff --git a/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java b/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java index 5a480c7..d01cc1e 100644 --- a/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java +++ b/device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java @@ -4,6 +4,7 @@ package org.chromium.device.bluetooth; +import android.Manifest; import android.annotation.TargetApi; import android.bluetooth.BluetoothDevice; import android.bluetooth.le.ScanFilter; @@ -18,7 +19,9 @@ import org.chromium.base.annotations.JNINamespace; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.UUID; /** @@ -33,6 +36,7 @@ class Fakes { * Fakes android.bluetooth.BluetoothAdapter. */ static class FakeBluetoothAdapter extends Wrappers.BluetoothAdapterWrapper { + private final FakeContext mFakeContext; private final FakeBluetoothLeScanner mFakeScanner; final long mNativeBluetoothTestAndroid; @@ -46,11 +50,17 @@ class Fakes { } private FakeBluetoothAdapter(long nativeBluetoothTestAndroid) { - super(null, new FakeBluetoothLeScanner()); + super(null, new FakeContext(), new FakeBluetoothLeScanner()); mNativeBluetoothTestAndroid = nativeBluetoothTestAndroid; + mFakeContext = (FakeContext) mContext; mFakeScanner = (FakeBluetoothLeScanner) mScanner; } + @CalledByNative("FakeBluetoothAdapter") + public void denyPermission() { + mFakeContext.mPermissions.clear(); + } + /** * Creates and discovers a new device. */ @@ -130,19 +140,30 @@ class Fakes { } /** + * Fakes android.content.Context. + */ + static class FakeContext extends Wrappers.ContextWrapper { + public final Set<String> mPermissions = new HashSet<String>(); + + public FakeContext() { + super(null); + mPermissions.add(Manifest.permission.ACCESS_COARSE_LOCATION); + } + + @Override + public boolean checkPermission(String permission) { + return mPermissions.contains(permission); + } + } + + /** * Fakes android.bluetooth.le.BluetoothLeScanner. */ static class FakeBluetoothLeScanner extends Wrappers.BluetoothLeScannerWrapper { public Wrappers.ScanCallbackWrapper mScanCallback; - public boolean mCanScan = true; private FakeBluetoothLeScanner() { - super(null, null); - } - - @Override - public boolean canScan() { - return mCanScan; + super(null); } @Override diff --git a/device/bluetooth/test/bluetooth_test.cc b/device/bluetooth/test/bluetooth_test.cc index 70d457f..c80b824 100644 --- a/device/bluetooth/test/bluetooth_test.cc +++ b/device/bluetooth/test/bluetooth_test.cc @@ -38,6 +38,10 @@ void BluetoothTestBase::StartLowEnergyDiscoverySession() { base::RunLoop().RunUntilIdle(); } +bool BluetoothTestBase::DenyPermission() { + return false; +} + BluetoothDevice* BluetoothTestBase::DiscoverLowEnergyDevice( int device_ordinal) { NOTIMPLEMENTED(); diff --git a/device/bluetooth/test/bluetooth_test.h b/device/bluetooth/test/bluetooth_test.h index c4f8687..e6ccc6c 100644 --- a/device/bluetooth/test/bluetooth_test.h +++ b/device/bluetooth/test/bluetooth_test.h @@ -65,6 +65,10 @@ class BluetoothTestBase : public testing::Test { // controlled by this test fixture. virtual void InitWithFakeAdapter(){}; + // Configures the fake adapter to lack the necessary permissions to scan for + // devices. Returns false if the current platform always has permission. + virtual bool DenyPermission(); + // Create a fake Low Energy device and discover it. // |device_ordinal| selects between multiple fake device data sets to produce: // 1: kTestDeviceName with advertised UUIDs kTestUUIDGenericAccess, diff --git a/device/bluetooth/test/bluetooth_test_android.cc b/device/bluetooth/test/bluetooth_test_android.cc index 28514f7..3e9d83f 100644 --- a/device/bluetooth/test/bluetooth_test_android.cc +++ b/device/bluetooth/test/bluetooth_test_android.cc @@ -57,6 +57,12 @@ void BluetoothTestAndroid::InitWithFakeAdapter() { BluetoothAdapterAndroid::Create(j_fake_bluetooth_adapter_.obj()).get(); } +bool BluetoothTestAndroid::DenyPermission() { + Java_FakeBluetoothAdapter_denyPermission(AttachCurrentThread(), + j_fake_bluetooth_adapter_.obj()); + return true; +} + BluetoothDevice* BluetoothTestAndroid::DiscoverLowEnergyDevice( int device_ordinal) { TestBluetoothAdapterObserver observer(adapter_); diff --git a/device/bluetooth/test/bluetooth_test_android.h b/device/bluetooth/test/bluetooth_test_android.h index d807e4c..0b917a7 100644 --- a/device/bluetooth/test/bluetooth_test_android.h +++ b/device/bluetooth/test/bluetooth_test_android.h @@ -26,6 +26,7 @@ class BluetoothTestAndroid : public BluetoothTestBase { void InitWithDefaultAdapter() override; void InitWithoutDefaultAdapter() override; void InitWithFakeAdapter() override; + bool DenyPermission() override; BluetoothDevice* DiscoverLowEnergyDevice(int device_ordinal) override; void SimulateGattConnection(BluetoothDevice* device) override; void SimulateGattConnectionError(BluetoothDevice* device, |