Chromium Code Reviews| Index: chrome/android/java/src/org/chromium/chrome/browser/BluetoothChooserDialog.java |
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/BluetoothChooserDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/BluetoothChooserDialog.java |
| index df15c1638c115883800da2309259c17a7c314a7d..59f8d26b3bb7c635a59c7b62b389cc8156b221ff 100644 |
| --- a/chrome/android/java/src/org/chromium/chrome/browser/BluetoothChooserDialog.java |
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/BluetoothChooserDialog.java |
| @@ -6,9 +6,11 @@ package org.chromium.chrome.browser; |
| import android.Manifest; |
| import android.app.Activity; |
| +import android.content.BroadcastReceiver; |
| import android.content.Context; |
| import android.content.Intent; |
| -import android.content.pm.PackageManager; |
| +import android.content.IntentFilter; |
| +import android.location.LocationManager; |
| import android.text.SpannableString; |
| import android.text.TextUtils; |
| import android.view.View; |
| @@ -28,6 +30,8 @@ import org.chromium.ui.text.SpanApplier.SpanInfo; |
| * A dialog for picking available Bluetooth devices. This dialog is shown when a website requests to |
| * pair with a certain class of Bluetooth devices (e.g. through a bluetooth.requestDevice Javascript |
| * call). |
| + * |
| + * The dialog is shown by create() or show(), and always runs finishDialog() as it's closing. |
| */ |
| public class BluetoothChooserDialog |
| implements ItemChooserDialog.ItemSelectedCallback, WindowAndroid.PermissionCallback { |
| @@ -68,6 +72,7 @@ public class BluetoothChooserDialog |
| ADAPTER_OFF, |
| ADAPTER_OFF_HELP, |
| REQUEST_LOCATION_PERMISSION, |
| + REQUEST_LOCATION_SERVICES, |
| NEED_LOCATION_PERMISSION_HELP, |
| RESTART_SEARCH, |
| } |
| @@ -130,30 +135,35 @@ public class BluetoothChooserDialog |
| new ItemChooserDialog.ItemChooserLabels(title, searching, noneFound, |
| statusIdleNoneFound, statusIdleSomeFound, positiveButton); |
| mItemChooserDialog = new ItemChooserDialog(mActivity, this, labels); |
| + |
| + mActivity.registerReceiver(mLocationModeBroadcastReceiver, |
| + new IntentFilter(LocationManager.MODE_CHANGED_ACTION)); |
|
Ted C
2016/07/01 20:18:34
does this give a lint warning? MODE_CHANGED_ACTIO
ortuno
2016/07/01 22:08:50
Hmm no lint errors. Is there anything I should do
Ted C
2016/07/01 22:22:56
While we lack the bluetooth permission prior to M,
|
| + } |
| + |
| + // Called to report the dialog's results back to native code. |
| + private void finishDialog(int resultCode, String id) { |
| + mActivity.unregisterReceiver(mLocationModeBroadcastReceiver); |
| + if (mNativeBluetoothChooserDialogPtr != 0) { |
| + nativeOnDialogFinished(mNativeBluetoothChooserDialogPtr, resultCode, id); |
| + } |
| } |
| @Override |
| public void onItemSelected(String id) { |
| - if (mNativeBluetoothChooserDialogPtr != 0) { |
| - if (id.isEmpty()) { |
| - nativeOnDialogFinished( |
| - mNativeBluetoothChooserDialogPtr, DIALOG_FINISHED_CANCELLED, ""); |
| - } else { |
| - nativeOnDialogFinished( |
| - mNativeBluetoothChooserDialogPtr, DIALOG_FINISHED_SELECTED, id); |
| - } |
| + if (id.isEmpty()) { |
| + finishDialog(DIALOG_FINISHED_CANCELLED, ""); |
| + } else { |
| + finishDialog(DIALOG_FINISHED_SELECTED, id); |
| } |
| } |
| @Override |
| public void onRequestPermissionsResult(String[] permissions, int[] grantResults) { |
| - for (int i = 0; i < grantResults.length; i++) { |
| + for (int i = 0; i < permissions.length; i++) { |
| if (permissions[i].equals(Manifest.permission.ACCESS_COARSE_LOCATION)) { |
| - if (grantResults[i] == PackageManager.PERMISSION_GRANTED) { |
| + if (checkLocationServicesAndPermission()) { |
| mItemChooserDialog.clear(); |
| nativeRestartSearch(mNativeBluetoothChooserDialogPtr); |
| - } else { |
| - checkLocationPermission(); |
| } |
| return; |
| } |
| @@ -161,24 +171,62 @@ public class BluetoothChooserDialog |
| // If the location permission is not present, leave the currently-shown message in place. |
| } |
| - private void checkLocationPermission() { |
| - if (LocationUtils.getInstance().hasAndroidLocationPermission(mActivity)) { |
| - return; |
| + @VisibleForTesting |
| + final BroadcastReceiver mLocationModeBroadcastReceiver = new BroadcastReceiver() { |
|
Ted C
2016/07/01 20:18:34
move this up to be with the other params (but at t
ortuno
2016/07/01 22:08:50
Done.
|
| + @Override |
| + public void onReceive(Context context, Intent intent) { |
| + if (LocationManager.MODE_CHANGED_ACTION.equals(intent.getAction())) { |
|
Ted C
2016/07/01 20:18:34
make this an early return to avoid indenting
ortuno
2016/07/01 22:08:50
Done.
|
| + if (checkLocationServicesAndPermission()) { |
| + mItemChooserDialog.clear(); |
| + nativeRestartSearch(mNativeBluetoothChooserDialogPtr); |
| + } |
| + } |
| } |
| + }; |
| - if (!mWindowAndroid.canRequestPermission(Manifest.permission.ACCESS_COARSE_LOCATION)) { |
| - if (mNativeBluetoothChooserDialogPtr != 0) { |
| - nativeOnDialogFinished( |
| - mNativeBluetoothChooserDialogPtr, DIALOG_FINISHED_DENIED_PERMISSION, ""); |
| - return; |
| - } |
| + // Returns true if Location Services is on and Chrome has permission to see the user's location. |
| + private boolean checkLocationServicesAndPermission() { |
| + final boolean havePermission = |
| + LocationUtils.getInstance().hasAndroidLocationPermission(mActivity); |
| + final boolean locationServicesOn = |
| + LocationUtils.getInstance().isSystemLocationSettingEnabled(mActivity); |
| + |
| + if (!havePermission |
| + && !mWindowAndroid.canRequestPermission( |
| + Manifest.permission.ACCESS_COARSE_LOCATION)) { |
| + // Immediately close the dialog because the user has asked Chrome not to request the |
| + // location permission. |
| + finishDialog(DIALOG_FINISHED_DENIED_PERMISSION, ""); |
| + return false; |
| } |
| - SpannableString needLocationMessage = SpanApplier.applySpans( |
| - mActivity.getString(R.string.bluetooth_need_location_permission), |
| - new SpanInfo("<link>", "</link>", |
| - new BluetoothClickableSpan( |
| - LinkType.REQUEST_LOCATION_PERMISSION, mActivity))); |
| + // Compute the message to show the user. |
| + final SpanInfo permissionSpan = new SpanInfo("<permission_link>", "</permission_link>", |
| + new BluetoothClickableSpan(LinkType.REQUEST_LOCATION_PERMISSION, mActivity)); |
| + final SpanInfo servicesSpan = new SpanInfo("<services_link>", "</services_link>", |
| + new BluetoothClickableSpan(LinkType.REQUEST_LOCATION_SERVICES, mActivity)); |
| + final SpannableString needLocationMessage; |
| + if (havePermission) { |
| + if (locationServicesOn) { |
| + // We don't need to request anything. |
| + return true; |
| + } else { |
| + needLocationMessage = SpanApplier.applySpans( |
| + mActivity.getString(R.string.bluetooth_need_location_services_on), |
| + servicesSpan); |
| + } |
| + } else { |
| + if (locationServicesOn) { |
| + needLocationMessage = SpanApplier.applySpans( |
| + mActivity.getString(R.string.bluetooth_need_location_permission), |
| + permissionSpan); |
| + } else { |
| + needLocationMessage = SpanApplier.applySpans( |
| + mActivity.getString( |
| + R.string.bluetooth_need_location_permission_and_services_on), |
| + permissionSpan, servicesSpan); |
| + } |
| + } |
| SpannableString needLocationStatus = SpanApplier.applySpans( |
| mActivity.getString(R.string.bluetooth_need_location_permission_help), |
| @@ -187,6 +235,7 @@ public class BluetoothChooserDialog |
| LinkType.NEED_LOCATION_PERMISSION_HELP, mActivity))); |
| mItemChooserDialog.setErrorState(needLocationMessage, needLocationStatus); |
| + return false; |
| } |
| private class BluetoothClickableSpan extends NoUnderlineClickableSpan { |
| @@ -233,6 +282,11 @@ public class BluetoothChooserDialog |
| BluetoothChooserDialog.this); |
| break; |
| } |
| + case REQUEST_LOCATION_SERVICES: { |
| + mContext.startActivity( |
| + LocationUtils.getInstance().getSystemLocationSettingsIntent()); |
| + break; |
| + } |
| case NEED_LOCATION_PERMISSION_HELP: { |
| nativeShowNeedLocationPermissionLink(mNativeBluetoothChooserDialogPtr); |
| closeDialog(); |
| @@ -314,9 +368,10 @@ public class BluetoothChooserDialog |
| void notifyDiscoveryState(int discoveryState) { |
| switch (discoveryState) { |
| case DISCOVERY_FAILED_TO_START: { |
| - // FAILED_TO_START might be caused by a missing Location permission. |
| + // FAILED_TO_START might be caused by a missing Location |
| + // permission or by the Location service being turned off. |
| // Check, and show a request if so. |
| - checkLocationPermission(); |
| + checkLocationServicesAndPermission(); |
| break; |
| } |
| case DISCOVERY_IDLE: { |