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 |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..087e4e2115c619a8586638f968ca2a0752a13c96 |
| --- /dev/null |
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/BluetoothChooserDialog.java |
| @@ -0,0 +1,237 @@ |
| +// Copyright 2015 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. |
| + |
| +package org.chromium.chrome.browser; |
| + |
| +import android.app.Activity; |
| +import android.content.Context; |
| +import android.content.Intent; |
| +import android.graphics.Color; |
| +import android.text.SpannableString; |
| +import android.text.TextPaint; |
| +import android.text.TextUtils; |
| +import android.text.style.ClickableSpan; |
| +import android.view.View; |
| + |
| +import org.chromium.base.annotations.CalledByNative; |
| +import org.chromium.chrome.R; |
| +import org.chromium.chrome.browser.omnibox.OmniboxUrlEmphasizer; |
| +import org.chromium.chrome.browser.profiles.Profile; |
| +import org.chromium.ui.base.WindowAndroid; |
| +import org.chromium.ui.text.SpanApplier; |
| +import org.chromium.ui.text.SpanApplier.SpanInfo; |
| + |
| +import java.util.ArrayList; |
| +import java.util.List; |
| + |
| +/** |
| + * A dialog for picking available Bluetooth devices. |
|
newt (away)
2015/09/01 21:51:23
Could you add a bit more context here. E.g. when i
Finnur
2015/09/02 16:01:43
Done.
|
| + */ |
| +public class BluetoothChooserDialog implements ItemChooserDialog.ItemSelectedCallback { |
| + Context mContext; |
| + |
| + // The dialog to show to let the user pick a device. |
| + ItemChooserDialog mItemChooserDialog; |
| + |
| + // The origin for the site wanting to pair with the bluetooth devices. |
| + String mOrigin; |
| + |
| + // The security level of the connection to the site wanting to pair with the |
| + // bluetooth devices. |
| + int mSecurityLevel; |
|
newt (away)
2015/09/01 21:51:23
What are the valid values for this variable? Are t
Finnur
2015/09/02 16:01:43
Done.
|
| + |
| + // A pointer back to the native part of the implementation for this dialog. |
| + long mNativeBluetoothChooserDialogPtr; |
| + |
| + // The type of link that is shown within the dialog. |
| + private enum LinkType { |
| + EXPLAIN_BLUETOOTH, |
| + EXPLAIN_PARING, |
| + ADAPTER_OFF, |
| + ADAPTER_OFF_HELP, |
| + RESTART_SEARCH, |
| + } |
| + |
| + /** |
| + * Creates the BluetoothChooserDialog and displays it (and starts waiting for data). |
| + * |
| + * @param context Context which is used for launching a dialog. |
| + */ |
| + public BluetoothChooserDialog(Context context, String origin, |
|
newt (away)
2015/09/01 21:51:23
If this is only called from create(), then make th
Finnur
2015/09/02 16:01:43
It didn't use to be, but is now. Fixed.
|
| + int securityLevel, long nativeBluetoothChooserDialogPtr) { |
| + mContext = context; |
| + mOrigin = origin; |
| + mSecurityLevel = securityLevel; |
| + mNativeBluetoothChooserDialogPtr = nativeBluetoothChooserDialogPtr; |
| + } |
| + |
| + /** |
| + * Show the BluetoothChooserDialog. |
| + */ |
| + public void show() { |
| + // Emphasize the origin. |
| + Profile profile = Profile.getLastUsedProfile(); |
| + SpannableString origin = new SpannableString(mOrigin); |
| + OmniboxUrlEmphasizer.emphasizeUrl(origin, mContext.getResources(), |
| + profile, mSecurityLevel, false, true, true); |
| + // Construct a full string and replace the origin text with emphasized version. |
| + String message = mContext.getString(R.string.bluetooth_dialog_title, mOrigin); |
| + SpannableString title = SpanApplier.applySpans( |
| + message, new SpanInfo("<link>", "</link>", |
| + new NoUnderlineClickableSpan(LinkType.EXPLAIN_PARING, mContext))); |
| + int start = title.toString().indexOf(mOrigin); |
|
newt (away)
2015/09/01 21:51:23
Instead of indexOf(), I'd use title.getSpanStart(t
Finnur
2015/09/02 16:01:43
I'n not sure how to use getSpanStart to accomplish
newt (away)
2015/09/02 17:48:42
Ah, I thought the span was wrapped around the orig
|
| + TextUtils.copySpansFrom(origin, 0, origin.length(), Object.class, title, start); |
| + |
| + message = mContext.getString(R.string.bluetooth_not_found); |
| + SpannableString noneFound = SpanApplier.applySpans( |
| + message, new SpanInfo("<link>", "</link>", |
| + new NoUnderlineClickableSpan(LinkType.RESTART_SEARCH, mContext))); |
| + |
| + String searching = mContext.getString(R.string.bluetooth_searching); |
| + String positiveButton = mContext.getString(R.string.bluetooth_confirm_button); |
| + |
| + SpannableString status = SpanApplier.applySpans( |
| + mContext.getString(R.string.bluetooth_not_seeing_it), |
| + new SpanInfo("<link1>", "</link1>", |
| + new NoUnderlineClickableSpan(LinkType.RESTART_SEARCH, mContext)), |
| + new SpanInfo("<link2>", "</link2>", |
| + new NoUnderlineClickableSpan(LinkType.EXPLAIN_BLUETOOTH, mContext))); |
| + |
| + SpannableString errorMessage = SpanApplier.applySpans( |
| + mContext.getString(R.string.bluetooth_adapter_off), |
| + new SpanInfo("<link>", "</link>", |
| + new NoUnderlineClickableSpan(LinkType.ADAPTER_OFF, mContext))); |
| + SpannableString errorStatus = SpanApplier.applySpans( |
| + mContext.getString(R.string.bluetooth_adapter_off_help), |
| + new SpanInfo("<link>", "</link>", |
| + new NoUnderlineClickableSpan(LinkType.ADAPTER_OFF_HELP, mContext))); |
| + |
| + ItemChooserDialog.ItemChooserLabels labels = |
| + new ItemChooserDialog.ItemChooserLabels(title, searching, noneFound, status, |
| + errorMessage, errorStatus, positiveButton); |
| + mItemChooserDialog = new ItemChooserDialog(mContext, this, labels); |
| + } |
| + |
| + @Override |
| + public void onItemSelected(String id) { |
| + if (mNativeBluetoothChooserDialogPtr != 0) { |
| + nativeReportDeviceSelected(mNativeBluetoothChooserDialogPtr, id); |
| + } |
| + } |
| + |
| + /** |
| + * A helper class to show a clickable link with underlines turned off. |
| + */ |
| + private class NoUnderlineClickableSpan extends ClickableSpan { |
| + // The type of link this span represents. |
| + private LinkType mLinkType; |
| + |
| + // TODO(finnur): Remove this variable when toasts have been eliminated. |
| + private Context mContext; |
| + |
| + NoUnderlineClickableSpan(LinkType linkType, Context context) { |
| + mLinkType = linkType; |
| + mContext = context; |
| + } |
| + |
| + @Override |
| + public void onClick(View view) { |
| + if (mNativeBluetoothChooserDialogPtr == 0) { |
| + return; |
| + } |
| + |
| + switch (mLinkType) { |
| + case EXPLAIN_BLUETOOTH: { |
| + if (mNativeBluetoothChooserDialogPtr != 0) { |
|
newt (away)
2015/09/01 21:51:23
This if check is redundant, since you already chec
Finnur
2015/09/02 16:01:43
Ah. Forgot about this. Fixed.
|
| + nativeShowBluetoothOverviewLink(mNativeBluetoothChooserDialogPtr); |
| + closeDialog(); |
| + } |
| + break; |
| + } |
| + case EXPLAIN_PARING: { |
| + if (mNativeBluetoothChooserDialogPtr != 0) { |
| + nativeShowBluetoothPairingLink(mNativeBluetoothChooserDialogPtr); |
| + closeDialog(); |
| + } |
| + break; |
| + } |
| + case ADAPTER_OFF: { |
| + Intent intent = new Intent(); |
| + intent.setAction(android.provider.Settings.ACTION_BLUETOOTH_SETTINGS); |
| + mContext.startActivity(intent); |
| + break; |
| + } |
| + case ADAPTER_OFF_HELP: { |
| + if (mNativeBluetoothChooserDialogPtr != 0) { |
| + nativeShowBluetoothAdapterOffLink(mNativeBluetoothChooserDialogPtr); |
| + closeDialog(); |
| + } |
| + break; |
| + } |
| + case RESTART_SEARCH: { |
| + mItemChooserDialog.clear(); |
| + if (mNativeBluetoothChooserDialogPtr != 0) { |
| + nativeReportRestartSearch(mNativeBluetoothChooserDialogPtr); |
| + } |
| + break; |
| + } |
| + default: |
| + assert false; |
| + } |
| + |
| + // Get rid of the highlight background on selection. |
| + view.invalidate(); |
| + } |
| + |
| + @Override |
| + public void updateDrawState(TextPaint textPaint) { |
| + super.updateDrawState(textPaint); |
| + textPaint.bgColor = Color.TRANSPARENT; |
| + textPaint.setUnderlineText(false); |
| + } |
| + } |
| + |
| + @CalledByNative |
| + private static BluetoothChooserDialog create( |
| + WindowAndroid windowAndroid, String origin, int securityLevel, |
| + long nativeBluetoothChooserDialogPtr) { |
| + Activity activity = windowAndroid.getActivity().get(); |
|
newt (away)
2015/09/01 21:51:23
windowAndroid.getActivity().get() can be null
Finnur
2015/09/02 16:01:43
Yes, I thought about that. Can we expect it to be
Ted C
2015/09/02 17:27:47
There are a couple cases where it can be null.
1.
Finnur
2015/09/03 11:51:45
Thanks for the explanation! I think I'll go with a
|
| + BluetoothChooserDialog dialog = new BluetoothChooserDialog( |
| + activity, origin, securityLevel, nativeBluetoothChooserDialogPtr); |
| + dialog.show(); |
| + return dialog; |
| + } |
| + |
| + @CalledByNative |
| + private void addDevice(String deviceId, String deviceName) { |
| + List<ItemChooserDialog.ItemChooserRow> devices = |
| + new ArrayList<ItemChooserDialog.ItemChooserRow>(); |
| + devices.add(new ItemChooserDialog.ItemChooserRow(deviceId, deviceName)); |
| + mItemChooserDialog.showList(devices); |
| + } |
| + |
| + @CalledByNative |
| + private void closeDialog() { |
|
newt (away)
2015/09/01 21:51:23
If the user closes the dialog via Java (e.g. by pr
Finnur
2015/09/02 16:01:43
The native side is owned by the RequestDeviceSessi
|
| + mNativeBluetoothChooserDialogPtr = 0; |
| + mItemChooserDialog.dismiss(); |
| + } |
| + |
| + @CalledByNative |
| + private void removeDevice(String deviceId) { |
| + mItemChooserDialog.setAvailability(deviceId, false); |
| + } |
| + |
| + @CalledByNative |
| + private void notifyAdapterTurnedOff() { |
| + mItemChooserDialog.setErrorState(); |
| + } |
| + |
| + private native void nativeReportDeviceSelected( |
| + long nativeBluetoothChooserAndroid, String deviceId); |
| + private native void nativeReportRestartSearch(long nativeBluetoothChooserAndroid); |
| + // Help links. |
| + private native void nativeShowBluetoothOverviewLink(long nativeBluetoothChooserAndroid); |
| + private native void nativeShowBluetoothPairingLink(long nativeBluetoothChooserAndroid); |
| + private native void nativeShowBluetoothAdapterOffLink(long nativeBluetoothChooserAndroid); |
| +} |