summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjyasskin <jyasskin@chromium.org>2015-11-18 11:55:37 -0800
committerCommit bot <commit-bot@chromium.org>2015-11-18 19:56:42 +0000
commit97ef21ed61bb27be090f0881db69b72e68047889 (patch)
tree51d5be34c43c78f36ba1e358ee9c04d3f22d9e7f
parent93e85639793d75edf25077db51d28f5403d56736 (diff)
downloadchromium_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}
-rw-r--r--device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothAdapter.java12
-rw-r--r--device/bluetooth/android/java/src/org/chromium/device/bluetooth/Wrappers.java46
-rw-r--r--device/bluetooth/bluetooth_adapter_unittest.cc22
-rw-r--r--device/bluetooth/test/android/java/src/org/chromium/device/bluetooth/Fakes.java37
-rw-r--r--device/bluetooth/test/bluetooth_test.cc4
-rw-r--r--device/bluetooth/test/bluetooth_test.h4
-rw-r--r--device/bluetooth/test/bluetooth_test_android.cc6
-rw-r--r--device/bluetooth/test/bluetooth_test_android.h1
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,